--- zzzz-none-000/linux-3.10.107/drivers/media/i2c/tvp514x.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/media/i2c/tvp514x.c 2021-02-04 17:41:59.000000000 +0000 @@ -35,11 +35,14 @@ #include #include #include +#include +#include +#include #include #include #include -#include +#include #include #include #include @@ -123,6 +126,8 @@ /* mc related members */ struct media_pad pad; struct v4l2_mbus_framefmt format; + + struct tvp514x_reg *int_seq; }; /* TVP514x default register values */ @@ -543,8 +548,6 @@ if (std_id == NULL) return -EINVAL; - *std_id = V4L2_STD_UNKNOWN; - /* To query the standard the TVP514x must power on the ADCs. */ if (!decoder->streaming) { tvp514x_s_stream(sd, 1); @@ -553,8 +556,10 @@ /* query the current standard */ current_std = tvp514x_query_current_std(sd); - if (current_std == STD_INVALID) + if (current_std == STD_INVALID) { + *std_id = V4L2_STD_UNKNOWN; return 0; + } input_sel = decoder->input; @@ -595,10 +600,12 @@ } /* check whether signal is locked */ sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); - if (lock_mask != (sync_lock_status & lock_mask)) + if (lock_mask != (sync_lock_status & lock_mask)) { + *std_id = V4L2_STD_UNKNOWN; return 0; /* No input detected */ + } - *std_id = decoder->std_list[current_std].standard.id; + *std_id &= decoder->std_list[current_std].standard.id; v4l2_dbg(1, debug, sd, "Current STD: %s\n", decoder->std_list[current_std].standard.name); @@ -740,54 +747,6 @@ } /** - * tvp514x_enum_mbus_fmt() - V4L2 decoder interface handler for enum_mbus_fmt - * @sd: pointer to standard V4L2 sub-device structure - * @index: index of pixelcode to retrieve - * @code: receives the pixelcode - * - * Enumerates supported mediabus formats - */ -static int -tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, - enum v4l2_mbus_pixelcode *code) -{ - if (index) - return -EINVAL; - - *code = V4L2_MBUS_FMT_YUYV10_2X10; - return 0; -} - -/** - * tvp514x_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt - * @sd: pointer to standard V4L2 sub-device structure - * @f: pointer to the mediabus format structure - * - * Negotiates the image capture size and mediabus format. - */ -static int -tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) -{ - struct tvp514x_decoder *decoder = to_decoder(sd); - enum tvp514x_std current_std; - - if (f == NULL) - return -EINVAL; - - /* Calculate height and width based on current standard */ - current_std = decoder->current_std; - - f->code = V4L2_MBUS_FMT_YUYV8_2X8; - f->width = decoder->std_list[current_std].width; - f->height = decoder->std_list[current_std].height; - f->field = V4L2_FIELD_INTERLACED; - f->colorspace = V4L2_COLORSPACE_SMPTE170M; - v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n", - f->width, f->height); - return 0; -} - -/** * tvp514x_g_parm() - V4L2 decoder interface handler for g_parm * @sd: pointer to standard V4L2 sub-device structure * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure @@ -862,7 +821,6 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) { int err = 0; - struct i2c_client *client = v4l2_get_subdevdata(sd); struct tvp514x_decoder *decoder = to_decoder(sd); if (decoder->streaming == enable) @@ -882,11 +840,8 @@ } case 1: { - struct tvp514x_reg *int_seq = (struct tvp514x_reg *) - client->driver->id_table->driver_data; - /* Power Up Sequence */ - err = tvp514x_write_regs(sd, int_seq); + err = tvp514x_write_regs(sd, decoder->int_seq); if (err) { v4l2_err(sd, "Unable to turn on decoder\n"); return err; @@ -920,13 +875,13 @@ /** * tvp514x_enum_mbus_code() - V4L2 decoder interface handler for enum_mbus_code * @sd: pointer to standard V4L2 sub-device structure - * @fh: file handle + * @cfg: pad configuration * @code: pointer to v4l2_subdev_mbus_code_enum structure * * Enumertaes mbus codes supported */ static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { u32 pad = code->pad; @@ -939,7 +894,7 @@ if (index != 0) return -EINVAL; - code->code = V4L2_MBUS_FMT_YUYV8_2X8; + code->code = MEDIA_BUS_FMT_YUYV8_2X8; return 0; } @@ -947,24 +902,27 @@ /** * tvp514x_get_pad_format() - V4L2 decoder interface handler for get pad format * @sd: pointer to standard V4L2 sub-device structure - * @fh: file handle + * @cfg: pad configuration * @format: pointer to v4l2_subdev_format structure * * Retrieves pad format which is active or tried based on requirement */ static int tvp514x_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) { struct tvp514x_decoder *decoder = to_decoder(sd); __u32 which = format->which; + if (format->pad) + return -EINVAL; + if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { format->format = decoder->format; return 0; } - format->format.code = V4L2_MBUS_FMT_YUYV8_2X8; + format->format.code = MEDIA_BUS_FMT_YUYV8_2X8; format->format.width = tvp514x_std_list[decoder->current_std].width; format->format.height = tvp514x_std_list[decoder->current_std].height; format->format.colorspace = V4L2_COLORSPACE_SMPTE170M; @@ -976,19 +934,19 @@ /** * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format * @sd: pointer to standard V4L2 sub-device structure - * @fh: file handle + * @cfg: pad configuration * @format: pointer to v4l2_subdev_format structure * * Set pad format for the output pad */ static int tvp514x_set_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct tvp514x_decoder *decoder = to_decoder(sd); if (fmt->format.field != V4L2_FIELD_INTERLACED || - fmt->format.code != V4L2_MBUS_FMT_YUYV8_2X8 || + fmt->format.code != MEDIA_BUS_FMT_YUYV8_2X8 || fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M || fmt->format.width != tvp514x_std_list[decoder->current_std].width || fmt->format.height != tvp514x_std_list[decoder->current_std].height) @@ -999,24 +957,10 @@ return 0; } -static const struct v4l2_subdev_core_ops tvp514x_core_ops = { - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, - .s_std = tvp514x_s_std, -}; - static const struct v4l2_subdev_video_ops tvp514x_video_ops = { + .s_std = tvp514x_s_std, .s_routing = tvp514x_s_routing, .querystd = tvp514x_querystd, - .enum_mbus_fmt = tvp514x_enum_mbus_fmt, - .g_mbus_fmt = tvp514x_mbus_fmt, - .try_mbus_fmt = tvp514x_mbus_fmt, - .s_mbus_fmt = tvp514x_mbus_fmt, .g_parm = tvp514x_g_parm, .s_parm = tvp514x_s_parm, .s_stream = tvp514x_s_stream, @@ -1029,7 +973,6 @@ }; static const struct v4l2_subdev_ops tvp514x_ops = { - .core = &tvp514x_core_ops, .video = &tvp514x_video_ops, .pad = &tvp514x_pad_ops, }; @@ -1055,6 +998,42 @@ }; +static struct tvp514x_platform_data * +tvp514x_get_pdata(struct i2c_client *client) +{ + struct tvp514x_platform_data *pdata; + struct v4l2_of_endpoint bus_cfg; + struct device_node *endpoint; + unsigned int flags; + + if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) + return client->dev.platform_data; + + endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); + if (!endpoint) + return NULL; + + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto done; + + v4l2_of_parse_endpoint(endpoint, &bus_cfg); + flags = bus_cfg.bus.parallel.flags; + + if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + pdata->hs_polarity = 1; + + if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + pdata->vs_polarity = 1; + + if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + pdata->clk_polarity = 1; + +done: + of_node_put(endpoint); + return pdata; +} + /** * tvp514x_probe() - decoder driver i2c probe handler * @client: i2c driver client device structure @@ -1066,19 +1045,20 @@ static int tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct tvp514x_platform_data *pdata = tvp514x_get_pdata(client); struct tvp514x_decoder *decoder; struct v4l2_subdev *sd; int ret; + if (pdata == NULL) { + dev_err(&client->dev, "No platform data\n"); + return -EINVAL; + } + /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - if (!client->dev.platform_data) { - v4l2_err(client, "No platform data!!\n"); - return -ENODEV; - } - decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; @@ -1089,8 +1069,10 @@ memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, sizeof(tvp514x_reg_list_default)); + decoder->int_seq = (struct tvp514x_reg *)id->driver_data; + /* Copy board specific information here */ - decoder->pdata = client->dev.platform_data; + decoder->pdata = pdata; /** * Fetch platform specific data, and configure the @@ -1109,7 +1091,6 @@ /* Register with V4L2 layer as slave device */ sd = &decoder->sd; v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); - strlcpy(sd->name, TVP514X_MODULE_NAME, sizeof(sd->name)); #if defined(CONFIG_MEDIA_CONTROLLER) decoder->pad.flags = MEDIA_PAD_FL_SOURCE; @@ -1120,7 +1101,6 @@ if (ret < 0) { v4l2_err(sd, "%s decoder driver failed to register !!\n", sd->name); - kfree(decoder); return ret; } #endif @@ -1138,16 +1118,22 @@ sd->ctrl_handler = &decoder->hdl; if (decoder->hdl.error) { ret = decoder->hdl.error; - - v4l2_ctrl_handler_free(&decoder->hdl); - return ret; + goto done; } v4l2_ctrl_handler_setup(&decoder->hdl); - v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); - - return 0; + ret = v4l2_async_register_subdev(&decoder->sd); + if (!ret) + v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); +done: + if (ret < 0) { + v4l2_ctrl_handler_free(&decoder->hdl); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&decoder->sd.entity); +#endif + } + return ret; } /** @@ -1162,7 +1148,7 @@ struct v4l2_subdev *sd = i2c_get_clientdata(client); struct tvp514x_decoder *decoder = to_decoder(sd); - v4l2_device_unregister_subdev(sd); + v4l2_async_unregister_subdev(&decoder->sd); #if defined(CONFIG_MEDIA_CONTROLLER) media_entity_cleanup(&decoder->sd.entity); #endif @@ -1231,8 +1217,20 @@ MODULE_DEVICE_TABLE(i2c, tvp514x_id); +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id tvp514x_of_match[] = { + { .compatible = "ti,tvp5146", }, + { .compatible = "ti,tvp5146m2", }, + { .compatible = "ti,tvp5147", }, + { .compatible = "ti,tvp5147m1", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tvp514x_of_match); +#endif + static struct i2c_driver tvp514x_driver = { .driver = { + .of_match_table = of_match_ptr(tvp514x_of_match), .owner = THIS_MODULE, .name = TVP514X_MODULE_NAME, },