Hi,friend.
we use ADV7482 and TX1 on our board.the adv7482 code has finished,but now we meet a problem.
I compile adv7482 driver as a module and I get the adv7482.ko. there is no /dev/video0 is created after insmod adv7482.ko;
I compile adv7482 into kernel and get new Image and zImage; the node of /dev/video0 is created after the new kernel is loaded .
the version of kernel loaded in TX1 is 3.10.96.
I have read the kernel code. I find the function tegra_vi_graph_init( ) and tegra_clean_unlinked_channels( ) are related to the unregister of /dev/video0. These functions can be find in the file of /kernel/drivers/media/platform/tegra/camera/graph.c. I find when the adv7482.ko hasn’t insmod,there is no link creatde between csi port and subdev ,so the tegra_clean_unlinked_channels( ) executes ,the dev/video0 is video_unregister_device.
My question is whether the adv7482 driver can be compiled as a module to insmod or not.if can ,how to to creat /dev/video0 in the way of insmod adv7482.ko.
the code of adv7482 driver is as follows:
static int adv7482_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct adv7482_state *state;
struct v4l2_subdev *sd;
static const struct v4l2_dv_timings cea1920x1080 = V4L2_DV_BT_DMT_1920X1080P60;
struct device_node *node = client->dev.of_node;
struct camera_common_data *common_data;
int err;
common_data = devm_kzalloc(&client->dev, sizeof(struct camera_common_data), GFP_KERNEL);
if (!common_data) {
dev_err(&client->dev, "unable to allocate memory!\n");
return -ENOMEM;
}
state = devm_kzalloc(&client->dev, sizeof(struct adv7482_state), GFP_KERNEL);
if (!state)
return -ENOMEM;
mutex_init(&state->mutex);
state->client = client;
state->cp.timings = cea1920x1080;
state->format = adv7482_format_info(V4L2_MBUS_FMT_UYVY8_1X16);
common_data->frmfmt = adv7482_frmfmt;
common_data->colorfmt = adv7482_find_datafmt(V4L2_MBUS_FMT_UYVY8_1X16);
common_data->numfmts = ARRAY_SIZE(adv7482_frmfmt);
common_data->priv = (void *)state;
common_data->i2c_client = client;
state->s_data = common_data;
state->sd = &common_data->subdev;
state->sd->dev = &client->dev;
state->s_data->dev = &client->dev;
err = adv7482_parse_dt(client, common_data);
if (err) {
dev_err(&client->dev, "Failed to find port info\n");
return err;
}
sd = state->sd;
v4l2_i2c_subdev_init(sd, client, &adv7482_ops);
if (adv7482_print_info(state) < 0) {
v4l2_err(sd, "not an adv7482 on address 0x%x\n", client->addr << 1);
return -ENODEV;
}
state->sd->internal_ops = &adv7482_subdev_internal_ops;
state->sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS|
V4L2_SUBDEV_FL_IS_I2C;
err = adv7482_register_clients(state);
if(err < 0) {
v4l2_err(sd, "failed to create all i2c clients\n");
goto err_i2c;
}
state->work_queues = create_singlethread_workqueue(client->name);
if(!state->work_queues) {
v4l2_err(sd, "Could not create work queue\n");
err = -ENOMEM;
goto err_work_queues;
}
adv7482_init(state);
state->pad.flags = MEDIA_PAD_FL_SOURCE;
state->sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_DECODER;
state->sd->entity.ops = &adv7482_media_ops;
err = media_entity_init(&state->sd->entity, 1, &state->pad, 0);
if (err < 0) {
dev_err(&client->dev, "unable to init media entity\n");
goto err_work_queues;
}
err = v4l2_async_register_subdev(sd);
if (err){
v4l2_err(sd, "v4l2_async_register_subdev error \n");
goto err_entity;
}
v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
client->addr << 1, client->adapter->name);
return 0;
err_entity:
media_entity_cleanup(&state->sd->entity);
err_work_queues:
destroy_workqueue(state->work_queues);
err_i2c:
adv7482_unregister_clients(state);
err_state:
kfree(state);
return err;
}