diff options
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r-- | drivers/media/i2c/ad9389b.c | 8 | ||||
-rw-r--r-- | drivers/media/i2c/adp1653.c | 4 | ||||
-rw-r--r-- | drivers/media/i2c/adv7180.c | 160 | ||||
-rw-r--r-- | drivers/media/i2c/adv7511.c | 6 | ||||
-rw-r--r-- | drivers/media/i2c/adv7604.c | 8 | ||||
-rw-r--r-- | drivers/media/i2c/adv7842.c | 6 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_controls.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/saa7115.c | 15 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-core.c | 12 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp.h | 1 | ||||
-rw-r--r-- | drivers/media/i2c/tc358743.c | 5 | ||||
-rw-r--r-- | drivers/media/i2c/ths7303.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/tvp5150.c | 9 |
13 files changed, 162 insertions, 76 deletions
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 788967dadd29..0462f461e679 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -1130,8 +1130,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * hdl = &state->hdl; v4l2_ctrl_handler_init(hdl, 5); - /* private controls */ - state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, 0, V4L2_DV_TX_MODE_DVI_D); @@ -1151,12 +1149,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * goto err_hdl; } - state->hdmi_mode_ctrl->is_private = true; - state->hotplug_ctrl->is_private = true; - state->rx_sense_ctrl->is_private = true; - state->have_edid0_ctrl->is_private = true; - state->rgb_quantization_range_ctrl->is_private = true; - state->pad.flags = MEDIA_PAD_FL_SINK; err = media_entity_pads_init(&sd->entity, 1, &state->pad); if (err) diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index fb7ed730d932..9e1731c565e7 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -466,9 +466,9 @@ static int adp1653_of_init(struct i2c_client *client, of_node_put(child); pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); - if (!pd->enable_gpio) { + if (IS_ERR(pd->enable_gpio)) { dev_err(&client->dev, "Error getting GPIO\n"); - return -EINVAL; + return PTR_ERR(pd->enable_gpio); } return 0; diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index ff57c1dcb8af..b77b0a4dbf68 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -26,8 +26,9 @@ #include <linux/i2c.h> #include <linux/slab.h> #include <linux/of.h> -#include <media/v4l2-ioctl.h> #include <linux/videodev2.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-event.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <linux/mutex.h> @@ -192,8 +193,8 @@ struct adv7180_state { struct mutex mutex; /* mutual excl. when accessing chip */ int irq; v4l2_std_id curr_norm; - bool autodetect; bool powered; + bool streaming; u8 input; struct i2c_client *client; @@ -338,12 +339,26 @@ static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) if (err) return err; - /* when we are interrupt driven we know the state */ - if (!state->autodetect || state->irq > 0) - *std = state->curr_norm; - else - err = __adv7180_status(state, NULL, std); + if (state->streaming) { + err = -EBUSY; + goto unlock; + } + + err = adv7180_set_video_standard(state, + ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM); + if (err) + goto unlock; + + msleep(100); + __adv7180_status(state, NULL, std); + + err = v4l2_std_to_adv7180(state->curr_norm); + if (err < 0) + goto unlock; + err = adv7180_set_video_standard(state, err); + +unlock: mutex_unlock(&state->mutex); return err; } @@ -387,23 +402,13 @@ static int adv7180_program_std(struct adv7180_state *state) { int ret; - if (state->autodetect) { - ret = adv7180_set_video_standard(state, - ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM); - if (ret < 0) - return ret; - - __adv7180_status(state, NULL, &state->curr_norm); - } else { - ret = v4l2_std_to_adv7180(state->curr_norm); - if (ret < 0) - return ret; - - ret = adv7180_set_video_standard(state, ret); - if (ret < 0) - return ret; - } + ret = v4l2_std_to_adv7180(state->curr_norm); + if (ret < 0) + return ret; + ret = adv7180_set_video_standard(state, ret); + if (ret < 0) + return ret; return 0; } @@ -415,18 +420,12 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) if (ret) return ret; - /* all standards -> autodetect */ - if (std == V4L2_STD_ALL) { - state->autodetect = true; - } else { - /* Make sure we can support this std */ - ret = v4l2_std_to_adv7180(std); - if (ret < 0) - goto out; + /* Make sure we can support this std */ + ret = v4l2_std_to_adv7180(std); + if (ret < 0) + goto out; - state->curr_norm = std; - state->autodetect = false; - } + state->curr_norm = std; ret = adv7180_program_std(state); out: @@ -434,6 +433,15 @@ out: return ret; } +static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm) +{ + struct adv7180_state *state = to_state(sd); + + *norm = state->curr_norm; + + return 0; +} + static int adv7180_set_power(struct adv7180_state *state, bool on) { u8 val; @@ -717,17 +725,77 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd, return 0; } +static int adv7180_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cropcap) +{ + struct adv7180_state *state = to_state(sd); + + if (state->curr_norm & V4L2_STD_525_60) { + cropcap->pixelaspect.numerator = 11; + cropcap->pixelaspect.denominator = 10; + } else { + cropcap->pixelaspect.numerator = 54; + cropcap->pixelaspect.denominator = 59; + } + + return 0; +} + +static int adv7180_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm) +{ + *norm = V4L2_STD_ALL; + return 0; +} + +static int adv7180_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct adv7180_state *state = to_state(sd); + int ret; + + /* It's always safe to stop streaming, no need to take the lock */ + if (!enable) { + state->streaming = enable; + return 0; + } + + /* Must wait until querystd released the lock */ + ret = mutex_lock_interruptible(&state->mutex); + if (ret) + return ret; + state->streaming = enable; + mutex_unlock(&state->mutex); + return 0; +} + +static int adv7180_subscribe_event(struct v4l2_subdev *sd, + struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_SOURCE_CHANGE: + return v4l2_src_change_event_subdev_subscribe(sd, fh, sub); + case V4L2_EVENT_CTRL: + return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub); + default: + return -EINVAL; + } +} + static const struct v4l2_subdev_video_ops adv7180_video_ops = { .s_std = adv7180_s_std, + .g_std = adv7180_g_std, .querystd = adv7180_querystd, .g_input_status = adv7180_g_input_status, .s_routing = adv7180_s_routing, .g_mbus_config = adv7180_g_mbus_config, + .cropcap = adv7180_cropcap, + .g_tvnorms = adv7180_g_tvnorms, + .s_stream = adv7180_s_stream, }; - static const struct v4l2_subdev_core_ops adv7180_core_ops = { .s_power = adv7180_s_power, + .subscribe_event = adv7180_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_pad_ops adv7180_pad_ops = { @@ -752,8 +820,14 @@ static irqreturn_t adv7180_irq(int irq, void *devid) /* clear */ adv7180_write(state, ADV7180_REG_ICR3, isr3); - if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) - __adv7180_status(state, NULL, &state->curr_norm); + if (isr3 & ADV7180_IRQ3_AD_CHANGE) { + static const struct v4l2_event src_ch = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, + }; + + v4l2_subdev_notify_event(&state->sd, &src_ch); + } mutex_unlock(&state->mutex); return IRQ_HANDLED; @@ -1198,7 +1272,7 @@ static int adv7180_probe(struct i2c_client *client, state->irq = client->irq; mutex_init(&state->mutex); - state->autodetect = true; + state->curr_norm = V4L2_STD_NTSC; if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED) state->powered = true; else @@ -1206,7 +1280,7 @@ static int adv7180_probe(struct i2c_client *client, state->input = 0; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); - sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; ret = adv7180_init_controls(state); if (ret) @@ -1328,6 +1402,14 @@ static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume); #ifdef CONFIG_OF static const struct of_device_id adv7180_of_id[] = { { .compatible = "adi,adv7180", }, + { .compatible = "adi,adv7182", }, + { .compatible = "adi,adv7280", }, + { .compatible = "adi,adv7280-m", }, + { .compatible = "adi,adv7281", }, + { .compatible = "adi,adv7281-m", }, + { .compatible = "adi,adv7281-ma", }, + { .compatible = "adi,adv7282", }, + { .compatible = "adi,adv7282-m", }, { }, }; diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index bd822f032b08..39271c35da48 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -1502,12 +1502,6 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * err = hdl->error; goto err_hdl; } - state->hdmi_mode_ctrl->is_private = true; - state->hotplug_ctrl->is_private = true; - state->rx_sense_ctrl->is_private = true; - state->have_edid0_ctrl->is_private = true; - state->rgb_quantization_range_ctrl->is_private = true; - state->pad.flags = MEDIA_PAD_FL_SINK; err = media_entity_pads_init(&sd->entity, 1, &state->pad); if (err) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 41a1bfc5eaa7..beb2841ceae5 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -3141,7 +3141,6 @@ static int adv76xx_probe(struct i2c_client *client, if (ctrl) ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; - /* private controls */ state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, (1 << state->info->num_dv_ports) - 1, 0, 0); @@ -3164,13 +3163,6 @@ static int adv76xx_probe(struct i2c_client *client, err = hdl->error; goto err_hdl; } - state->detect_tx_5v_ctrl->is_private = true; - state->rgb_quantization_range_ctrl->is_private = true; - if (adv76xx_has_afe(state)) - state->analog_sampling_phase_ctrl->is_private = true; - state->free_run_color_manual_ctrl->is_private = true; - state->free_run_color_ctrl->is_private = true; - if (adv76xx_s_detect_tx_5v_ctrl(sd)) { err = -ENODEV; goto err_hdl; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 7ccb85d45224..ecaacb0a6fa1 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -3300,12 +3300,6 @@ static int adv7842_probe(struct i2c_client *client, err = hdl->error; goto err_hdl; } - state->detect_tx_5v_ctrl->is_private = true; - state->rgb_quantization_range_ctrl->is_private = true; - state->analog_sampling_phase_ctrl->is_private = true; - state->free_run_color_ctrl_manual->is_private = true; - state->free_run_color_ctrl->is_private = true; - if (adv7842_s_detect_tx_5v_ctrl(sd)) { err = -ENODEV; goto err_hdl; diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c index a60931e66312..c2218c0a9e6f 100644 --- a/drivers/media/i2c/m5mols/m5mols_controls.c +++ b/drivers/media/i2c/m5mols/m5mols_controls.c @@ -405,7 +405,7 @@ static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl) struct v4l2_subdev *sd = to_sd(ctrl); struct m5mols_info *info = to_m5mols(sd); int ret = 0; - u8 status; + u8 status = REG_ISO_AUTO; v4l2_dbg(1, m5mols_debug, sd, "%s: ctrl: %s (%d)\n", __func__, ctrl->name, info->isp_ready); diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index d2a1ce2bc7f5..bd3526bdd539 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1798,6 +1798,21 @@ static int saa711x_detect_chip(struct i2c_client *client, return GM7113C; } + /* Check if it is a CJC7113 */ + if (!memcmp(name, "1111111111111111", CHIP_VER_SIZE)) { + strlcpy(name, "cjc7113", CHIP_VER_SIZE); + + if (!autodetect && strcmp(name, id->name)) + return -EINVAL; + + v4l_dbg(1, debug, client, + "It seems to be a %s chip (%*ph) @ 0x%x.\n", + name, 16, chip_ver, client->addr << 1); + + /* CJC7113 seems to be SAA7113-compatible */ + return SAA7113; + } + /* Chip was not discovered. Return its ID and don't bind */ v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n", 16, chip_ver, client->addr << 1); diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index a215efe7a8ba..3dfe387abf6e 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -188,6 +188,8 @@ static int smiapp_read_frame_fmt(struct smiapp_sensor *sensor) embedded_end = 0; } + sensor->image_start = image_start; + dev_dbg(&client->dev, "embedded data from lines %d to %d\n", embedded_start, embedded_end); dev_dbg(&client->dev, "image data starts at line %d\n", image_start); @@ -2280,6 +2282,15 @@ static int smiapp_get_skip_frames(struct v4l2_subdev *subdev, u32 *frames) return 0; } +static int smiapp_get_skip_top_lines(struct v4l2_subdev *subdev, u32 *lines) +{ + struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); + + *lines = sensor->image_start; + + return 0; +} + /* ----------------------------------------------------------------------------- * sysfs attributes */ @@ -2890,6 +2901,7 @@ static const struct v4l2_subdev_pad_ops smiapp_pad_ops = { static const struct v4l2_subdev_sensor_ops smiapp_sensor_ops = { .g_skip_frames = smiapp_get_skip_frames, + .g_skip_top_lines = smiapp_get_skip_top_lines, }; static const struct v4l2_subdev_ops smiapp_ops = { diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h index f6af0cc4a256..2174f89a00db 100644 --- a/drivers/media/i2c/smiapp/smiapp.h +++ b/drivers/media/i2c/smiapp/smiapp.h @@ -217,6 +217,7 @@ struct smiapp_sensor { u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */ u8 frame_skip; + u16 image_start; /* Offset to first line after metadata lines */ int power_count; diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 972e0d47259d..6cf6d06737a5 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1551,6 +1551,8 @@ static int tc358743_g_edid(struct v4l2_subdev *sd, { struct tc358743_state *state = to_state(sd); + memset(edid->reserved, 0, sizeof(edid->reserved)); + if (edid->pad != 0) return -EINVAL; @@ -1585,6 +1587,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", __func__, edid->pad, edid->start_block, edid->blocks); + memset(edid->reserved, 0, sizeof(edid->reserved)); + if (edid->pad != 0) return -EINVAL; @@ -1859,7 +1863,6 @@ static int tc358743_probe(struct i2c_client *client, /* control handlers */ v4l2_ctrl_handler_init(&state->hdl, 3); - /* private controls */ state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&state->hdl, NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 5bbfcab01c75..71a31352135c 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -285,7 +285,7 @@ static int ths7303_log_status(struct v4l2_subdev *sd) v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off"); if (state->bt.pixelclock) { - struct v4l2_bt_timings *bt = bt = &state->bt; + struct v4l2_bt_timings *bt = &state->bt; u32 frame_width, frame_height; frame_width = V4L2_DV_BT_FRAME_WIDTH(bt); diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index ff18444e19e4..0b6d46c453bf 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -83,7 +83,7 @@ static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr) return rc; } -static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr, +static int tvp5150_write(struct v4l2_subdev *sd, unsigned char addr, unsigned char value) { struct i2c_client *c = v4l2_get_subdevdata(sd); @@ -92,7 +92,9 @@ static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr, v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", addr, value); rc = i2c_smbus_write_byte_data(c, addr, value); if (rc < 0) - v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d\n", rc); + v4l2_err(sd, "i2c i/o error: rc == %d\n", rc); + + return rc; } static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init, @@ -1159,8 +1161,7 @@ static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff); - return 0; + return tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff); } #endif |