diff options
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r-- | drivers/media/i2c/Kconfig | 11 | ||||
-rw-r--r-- | drivers/media/i2c/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/i2c/ad9389b.c | 15 | ||||
-rw-r--r-- | drivers/media/i2c/adv7183.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/adv7343.c | 1 | ||||
-rw-r--r-- | drivers/media/i2c/adv7511.c | 18 | ||||
-rw-r--r-- | drivers/media/i2c/adv7842.c | 30 | ||||
-rw-r--r-- | drivers/media/i2c/lm3560.c | 488 | ||||
-rw-r--r-- | drivers/media/i2c/s5c73m3/s5c73m3-core.c | 4 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/imx074.c | 4 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9640.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/ths8200.c | 13 | ||||
-rw-r--r-- | drivers/media/i2c/tvp514x.c | 1 | ||||
-rw-r--r-- | drivers/media/i2c/tvp7002.c | 1 |
14 files changed, 541 insertions, 50 deletions
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index d18be19c96cd..842654d33317 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -621,6 +621,15 @@ config VIDEO_AS3645A This is a driver for the AS3645A and LM3555 flash controllers. It has build in control for flash, torch and indicator LEDs. +config VIDEO_LM3560 + tristate "LM3560 dual flash driver support" + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on MEDIA_CAMERA_SUPPORT + select REGMAP_I2C + ---help--- + This is a driver for the lm3560 dual flash controllers. It controls + flash, torch LEDs. + comment "Video improvement chips" config VIDEO_UPD64031A @@ -646,7 +655,7 @@ config VIDEO_UPD64083 To compile this driver as a module, choose M here: the module will be called upd64083. -comment "Miscelaneous helper chips" +comment "Miscellaneous helper chips" config VIDEO_THS7303 tristate "THS7303/53 Video Amplifier" diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 9f462df77b4a..e03f1776f4f4 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/ obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o +obj-$(CONFIG_VIDEO_LM3560) += lm3560.o obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o obj-$(CONFIG_VIDEO_AK881X) += ak881x.o obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index bb0c99d7a4f1..b06a7e54ee0d 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -628,16 +628,13 @@ static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable) static const struct v4l2_dv_timings_cap ad9389b_timings_cap = { .type = V4L2_DV_BT_656_1120, - .bt = { - .max_width = 1920, - .max_height = 1200, - .min_pixelclock = 25000000, - .max_pixelclock = 170000000, - .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000, + V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, - .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | - V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, - }, + V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) }; static int ad9389b_s_dv_timings(struct v4l2_subdev *sd, diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 6f738d8e3a8f..d45e0e3a781d 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -178,7 +178,7 @@ static int adv7183_log_status(struct v4l2_subdev *sd) adv7183_read(sd, ADV7183_VS_FIELD_CTRL_1), adv7183_read(sd, ADV7183_VS_FIELD_CTRL_2), adv7183_read(sd, ADV7183_VS_FIELD_CTRL_3)); - v4l2_info(sd, "adv7183: Hsync positon control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", + v4l2_info(sd, "adv7183: Hsync position control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", adv7183_read(sd, ADV7183_HS_POS_CTRL_1), adv7183_read(sd, ADV7183_HS_POS_CTRL_2), adv7183_read(sd, ADV7183_HS_POS_CTRL_3)); diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index aeb56c53e39f..d4e15a617c3b 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -25,6 +25,7 @@ #include <linux/module.h> #include <linux/videodev2.h> #include <linux/uaccess.h> +#include <linux/of.h> #include <media/adv7343.h> #include <media/v4l2-async.h> diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 7a576097471f..7c8d971f1f61 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -119,16 +119,14 @@ static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq); static const struct v4l2_dv_timings_cap adv7511_timings_cap = { .type = V4L2_DV_BT_656_1120, - .bt = { - .max_width = ADV7511_MAX_WIDTH, - .max_height = ADV7511_MAX_HEIGHT, - .min_pixelclock = ADV7511_MIN_PIXELCLOCK, - .max_pixelclock = ADV7511_MAX_PIXELCLOCK, - .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, ADV7511_MAX_WIDTH, 0, ADV7511_MAX_HEIGHT, + ADV7511_MIN_PIXELCLOCK, ADV7511_MAX_PIXELCLOCK, + V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, - .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | - V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, - }, + V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) }; static inline struct adv7511_state *get_adv7511_state(struct v4l2_subdev *sd) @@ -1126,6 +1124,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * state->i2c_edid = i2c_new_dummy(client->adapter, state->i2c_edid_addr >> 1); if (state->i2c_edid == NULL) { v4l2_err(sd, "failed to register edid i2c client\n"); + err = -ENOMEM; goto err_entity; } @@ -1133,6 +1132,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * state->work_queue = create_singlethread_workqueue(sd->name); if (state->work_queue == NULL) { v4l2_err(sd, "could not create workqueue\n"); + err = -ENOMEM; goto err_unreg_cec; } diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index d1748901337c..22f729d66a96 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -546,30 +546,24 @@ static inline bool is_digital_input(struct v4l2_subdev *sd) static const struct v4l2_dv_timings_cap adv7842_timings_cap_analog = { .type = V4L2_DV_BT_656_1120, - .bt = { - .max_width = 1920, - .max_height = 1200, - .min_pixelclock = 25000000, - .max_pixelclock = 170000000, - .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000, + V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, - .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | - V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, - }, + V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) }; static const struct v4l2_dv_timings_cap adv7842_timings_cap_digital = { .type = V4L2_DV_BT_656_1120, - .bt = { - .max_width = 1920, - .max_height = 1200, - .min_pixelclock = 25000000, - .max_pixelclock = 225000000, - .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 225000000, + V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, - .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | - V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, - }, + V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) }; static inline const struct v4l2_dv_timings_cap * diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c new file mode 100644 index 000000000000..3317a9ae3961 --- /dev/null +++ b/drivers/media/i2c/lm3560.c @@ -0,0 +1,488 @@ +/* + * drivers/media/i2c/lm3560.c + * General device driver for TI lm3560, FLASH LED Driver + * + * Copyright (C) 2013 Texas Instruments + * + * Contact: Daniel Jeong <gshark.jeong@gmail.com> + * Ldd-Mlp <ldd-mlp@list.ti.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/regmap.h> +#include <linux/videodev2.h> +#include <media/lm3560.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> + +/* registers definitions */ +#define REG_ENABLE 0x10 +#define REG_TORCH_BR 0xa0 +#define REG_FLASH_BR 0xb0 +#define REG_FLASH_TOUT 0xc0 +#define REG_FLAG 0xd0 +#define REG_CONFIG1 0xe0 + +/* Fault Mask */ +#define FAULT_TIMEOUT (1<<0) +#define FAULT_OVERTEMP (1<<1) +#define FAULT_SHORT_CIRCUIT (1<<2) + +enum led_enable { + MODE_SHDN = 0x0, + MODE_TORCH = 0x2, + MODE_FLASH = 0x3, +}; + +/* struct lm3560_flash + * + * @pdata: platform data + * @regmap: reg. map for i2c + * @lock: muxtex for serial access. + * @led_mode: V4L2 LED mode + * @ctrls_led: V4L2 contols + * @subdev_led: V4L2 subdev + */ +struct lm3560_flash { + struct device *dev; + struct lm3560_platform_data *pdata; + struct regmap *regmap; + struct mutex lock; + + enum v4l2_flash_led_mode led_mode; + struct v4l2_ctrl_handler ctrls_led[LM3560_LED_MAX]; + struct v4l2_subdev subdev_led[LM3560_LED_MAX]; +}; + +#define to_lm3560_flash(_ctrl, _no) \ + container_of(_ctrl->handler, struct lm3560_flash, ctrls_led[_no]) + +/* enable mode control */ +static int lm3560_mode_ctrl(struct lm3560_flash *flash) +{ + int rval = -EINVAL; + + switch (flash->led_mode) { + case V4L2_FLASH_LED_MODE_NONE: + rval = regmap_update_bits(flash->regmap, + REG_ENABLE, 0x03, MODE_SHDN); + break; + case V4L2_FLASH_LED_MODE_TORCH: + rval = regmap_update_bits(flash->regmap, + REG_ENABLE, 0x03, MODE_TORCH); + break; + case V4L2_FLASH_LED_MODE_FLASH: + rval = regmap_update_bits(flash->regmap, + REG_ENABLE, 0x03, MODE_FLASH); + break; + } + return rval; +} + +/* led1/2 enable/disable */ +static int lm3560_enable_ctrl(struct lm3560_flash *flash, + enum lm3560_led_id led_no, bool on) +{ + int rval; + + if (led_no == LM3560_LED0) { + if (on == true) + rval = regmap_update_bits(flash->regmap, + REG_ENABLE, 0x08, 0x08); + else + rval = regmap_update_bits(flash->regmap, + REG_ENABLE, 0x08, 0x00); + } else { + if (on == true) + rval = regmap_update_bits(flash->regmap, + REG_ENABLE, 0x10, 0x10); + else + rval = regmap_update_bits(flash->regmap, + REG_ENABLE, 0x10, 0x00); + } + return rval; +} + +/* torch1/2 brightness control */ +static int lm3560_torch_brt_ctrl(struct lm3560_flash *flash, + enum lm3560_led_id led_no, unsigned int brt) +{ + int rval; + u8 br_bits; + + if (brt < LM3560_TORCH_BRT_MIN) + return lm3560_enable_ctrl(flash, led_no, false); + else + rval = lm3560_enable_ctrl(flash, led_no, true); + + br_bits = LM3560_TORCH_BRT_uA_TO_REG(brt); + if (led_no == LM3560_LED0) + rval = regmap_update_bits(flash->regmap, + REG_TORCH_BR, 0x07, br_bits); + else + rval = regmap_update_bits(flash->regmap, + REG_TORCH_BR, 0x38, br_bits << 3); + + return rval; +} + +/* flash1/2 brightness control */ +static int lm3560_flash_brt_ctrl(struct lm3560_flash *flash, + enum lm3560_led_id led_no, unsigned int brt) +{ + int rval; + u8 br_bits; + + if (brt < LM3560_FLASH_BRT_MIN) + return lm3560_enable_ctrl(flash, led_no, false); + else + rval = lm3560_enable_ctrl(flash, led_no, true); + + br_bits = LM3560_FLASH_BRT_uA_TO_REG(brt); + if (led_no == LM3560_LED0) + rval = regmap_update_bits(flash->regmap, + REG_FLASH_BR, 0x0f, br_bits); + else + rval = regmap_update_bits(flash->regmap, + REG_FLASH_BR, 0xf0, br_bits << 4); + + return rval; +} + +/* V4L2 controls */ +static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no) +{ + struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no); + + mutex_lock(&flash->lock); + + if (ctrl->id == V4L2_CID_FLASH_FAULT) { + int rval; + s32 fault = 0; + unsigned int reg_val; + rval = regmap_read(flash->regmap, REG_FLAG, ®_val); + if (rval < 0) + return rval; + if (rval & FAULT_SHORT_CIRCUIT) + fault |= V4L2_FLASH_FAULT_SHORT_CIRCUIT; + if (rval & FAULT_OVERTEMP) + fault |= V4L2_FLASH_FAULT_OVER_TEMPERATURE; + if (rval & FAULT_TIMEOUT) + fault |= V4L2_FLASH_FAULT_TIMEOUT; + ctrl->cur.val = fault; + return 0; + } + + mutex_unlock(&flash->lock); + return -EINVAL; +} + +static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no) +{ + struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no); + u8 tout_bits; + int rval = -EINVAL; + + mutex_lock(&flash->lock); + + switch (ctrl->id) { + case V4L2_CID_FLASH_LED_MODE: + flash->led_mode = ctrl->val; + if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) + rval = lm3560_mode_ctrl(flash); + break; + + case V4L2_CID_FLASH_STROBE_SOURCE: + rval = regmap_update_bits(flash->regmap, + REG_CONFIG1, 0x04, (ctrl->val) << 2); + if (rval < 0) + goto err_out; + break; + + case V4L2_CID_FLASH_STROBE: + if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) + return -EBUSY; + flash->led_mode = V4L2_FLASH_LED_MODE_FLASH; + rval = lm3560_mode_ctrl(flash); + break; + + case V4L2_CID_FLASH_STROBE_STOP: + if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) + return -EBUSY; + flash->led_mode = V4L2_FLASH_LED_MODE_NONE; + rval = lm3560_mode_ctrl(flash); + break; + + case V4L2_CID_FLASH_TIMEOUT: + tout_bits = LM3560_FLASH_TOUT_ms_TO_REG(ctrl->val); + rval = regmap_update_bits(flash->regmap, + REG_FLASH_TOUT, 0x1f, tout_bits); + break; + + case V4L2_CID_FLASH_INTENSITY: + rval = lm3560_flash_brt_ctrl(flash, led_no, ctrl->val); + break; + + case V4L2_CID_FLASH_TORCH_INTENSITY: + rval = lm3560_torch_brt_ctrl(flash, led_no, ctrl->val); + break; + } + + mutex_unlock(&flash->lock); +err_out: + return rval; +} + +static int lm3560_led1_get_ctrl(struct v4l2_ctrl *ctrl) +{ + return lm3560_get_ctrl(ctrl, LM3560_LED1); +} + +static int lm3560_led1_set_ctrl(struct v4l2_ctrl *ctrl) +{ + return lm3560_set_ctrl(ctrl, LM3560_LED1); +} + +static int lm3560_led0_get_ctrl(struct v4l2_ctrl *ctrl) +{ + return lm3560_get_ctrl(ctrl, LM3560_LED0); +} + +static int lm3560_led0_set_ctrl(struct v4l2_ctrl *ctrl) +{ + return lm3560_set_ctrl(ctrl, LM3560_LED0); +} + +static const struct v4l2_ctrl_ops lm3560_led_ctrl_ops[LM3560_LED_MAX] = { + [LM3560_LED0] = { + .g_volatile_ctrl = lm3560_led0_get_ctrl, + .s_ctrl = lm3560_led0_set_ctrl, + }, + [LM3560_LED1] = { + .g_volatile_ctrl = lm3560_led1_get_ctrl, + .s_ctrl = lm3560_led1_set_ctrl, + } +}; + +static int lm3560_init_controls(struct lm3560_flash *flash, + enum lm3560_led_id led_no) +{ + struct v4l2_ctrl *fault; + u32 max_flash_brt = flash->pdata->max_flash_brt[led_no]; + u32 max_torch_brt = flash->pdata->max_torch_brt[led_no]; + struct v4l2_ctrl_handler *hdl = &flash->ctrls_led[led_no]; + const struct v4l2_ctrl_ops *ops = &lm3560_led_ctrl_ops[led_no]; + + v4l2_ctrl_handler_init(hdl, 8); + /* flash mode */ + v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_LED_MODE, + V4L2_FLASH_LED_MODE_TORCH, ~0x7, + V4L2_FLASH_LED_MODE_NONE); + flash->led_mode = V4L2_FLASH_LED_MODE_NONE; + + /* flash source */ + v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_STROBE_SOURCE, + 0x1, ~0x3, V4L2_FLASH_STROBE_SOURCE_SOFTWARE); + + /* flash strobe */ + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE, 0, 0, 0, 0); + /* flash strobe stop */ + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0); + + /* flash strobe timeout */ + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TIMEOUT, + LM3560_FLASH_TOUT_MIN, + flash->pdata->max_flash_timeout, + LM3560_FLASH_TOUT_STEP, + flash->pdata->max_flash_timeout); + + /* flash brt */ + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY, + LM3560_FLASH_BRT_MIN, max_flash_brt, + LM3560_FLASH_BRT_STEP, max_flash_brt); + + /* torch brt */ + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TORCH_INTENSITY, + LM3560_TORCH_BRT_MIN, max_torch_brt, + LM3560_TORCH_BRT_STEP, max_torch_brt); + + /* fault */ + fault = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_FAULT, 0, + V4L2_FLASH_FAULT_OVER_VOLTAGE + | V4L2_FLASH_FAULT_OVER_TEMPERATURE + | V4L2_FLASH_FAULT_SHORT_CIRCUIT + | V4L2_FLASH_FAULT_TIMEOUT, 0, 0); + if (fault != NULL) + fault->flags |= V4L2_CTRL_FLAG_VOLATILE; + + if (hdl->error) + return hdl->error; + + flash->subdev_led[led_no].ctrl_handler = hdl; + return 0; +} + +/* initialize device */ +static const struct v4l2_subdev_ops lm3560_ops = { + .core = NULL, +}; + +static const struct regmap_config lm3560_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xFF, +}; + +static int lm3560_subdev_init(struct lm3560_flash *flash, + enum lm3560_led_id led_no, char *led_name) +{ + struct i2c_client *client = to_i2c_client(flash->dev); + int rval; + + v4l2_i2c_subdev_init(&flash->subdev_led[led_no], client, &lm3560_ops); + flash->subdev_led[led_no].flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + strcpy(flash->subdev_led[led_no].name, led_name); + rval = lm3560_init_controls(flash, led_no); + if (rval) + goto err_out; + rval = media_entity_init(&flash->subdev_led[led_no].entity, 0, NULL, 0); + if (rval < 0) + goto err_out; + flash->subdev_led[led_no].entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH; + + return rval; + +err_out: + v4l2_ctrl_handler_free(&flash->ctrls_led[led_no]); + return rval; +} + +static int lm3560_init_device(struct lm3560_flash *flash) +{ + int rval; + unsigned int reg_val; + + /* set peak current */ + rval = regmap_update_bits(flash->regmap, + REG_FLASH_TOUT, 0x60, flash->pdata->peak); + if (rval < 0) + return rval; + /* output disable */ + flash->led_mode = V4L2_FLASH_LED_MODE_NONE; + rval = lm3560_mode_ctrl(flash); + if (rval < 0) + return rval; + /* Reset faults */ + rval = regmap_read(flash->regmap, REG_FLAG, ®_val); + return rval; +} + +static int lm3560_probe(struct i2c_client *client, + const struct i2c_device_id *devid) +{ + struct lm3560_flash *flash; + struct lm3560_platform_data *pdata = dev_get_platdata(&client->dev); + int rval; + + flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL); + if (flash == NULL) + return -ENOMEM; + + flash->regmap = devm_regmap_init_i2c(client, &lm3560_regmap); + if (IS_ERR(flash->regmap)) { + rval = PTR_ERR(flash->regmap); + return rval; + } + + /* if there is no platform data, use chip default value */ + if (pdata == NULL) { + pdata = + kzalloc(sizeof(struct lm3560_platform_data), GFP_KERNEL); + if (pdata == NULL) + return -ENODEV; + pdata->peak = LM3560_PEAK_3600mA; + pdata->max_flash_timeout = LM3560_FLASH_TOUT_MAX; + /* led 1 */ + pdata->max_flash_brt[LM3560_LED0] = LM3560_FLASH_BRT_MAX; + pdata->max_torch_brt[LM3560_LED0] = LM3560_TORCH_BRT_MAX; + /* led 2 */ + pdata->max_flash_brt[LM3560_LED1] = LM3560_FLASH_BRT_MAX; + pdata->max_torch_brt[LM3560_LED1] = LM3560_TORCH_BRT_MAX; + } + flash->pdata = pdata; + flash->dev = &client->dev; + mutex_init(&flash->lock); + + rval = lm3560_subdev_init(flash, LM3560_LED0, "lm3560-led0"); + if (rval < 0) + return rval; + + rval = lm3560_subdev_init(flash, LM3560_LED1, "lm3560-led1"); + if (rval < 0) + return rval; + + rval = lm3560_init_device(flash); + if (rval < 0) + return rval; + + return 0; +} + +static int lm3560_remove(struct i2c_client *client) +{ + struct v4l2_subdev *subdev = i2c_get_clientdata(client); + struct lm3560_flash *flash = container_of(subdev, struct lm3560_flash, + subdev_led[LM3560_LED_MAX]); + unsigned int i; + + for (i = LM3560_LED0; i < LM3560_LED_MAX; i++) { + v4l2_device_unregister_subdev(&flash->subdev_led[i]); + v4l2_ctrl_handler_free(&flash->ctrls_led[i]); + media_entity_cleanup(&flash->subdev_led[i].entity); + } + + return 0; +} + +static const struct i2c_device_id lm3560_id_table[] = { + {LM3560_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, lm3560_id_table); + +static struct i2c_driver lm3560_i2c_driver = { + .driver = { + .name = LM3560_NAME, + .pm = NULL, + }, + .probe = lm3560_probe, + .remove = lm3560_remove, + .id_table = lm3560_id_table, +}; + +module_i2c_driver(lm3560_i2c_driver); + +MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>"); +MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>"); +MODULE_DESCRIPTION("Texas Instruments LM3560 LED flash driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index b76ec0e7e685..6fec9384d86e 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1581,7 +1581,7 @@ static int s5c73m3_probe(struct i2c_client *client, oif_sd = &state->oif_sd; v4l2_subdev_init(sd, &s5c73m3_subdev_ops); - sd->owner = client->driver->driver.owner; + sd->owner = client->dev.driver->owner; v4l2_set_subdevdata(sd, state); strlcpy(sd->name, "S5C73M3", sizeof(sd->name)); @@ -1651,7 +1651,7 @@ static int s5c73m3_probe(struct i2c_client *client, if (ret < 0) goto out_err; - v4l2_info(sd, "%s: completed succesfully\n", __func__); + v4l2_info(sd, "%s: completed successfully\n", __func__); return 0; out_err: diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c index 1d384a371b41..5b915936c3f3 100644 --- a/drivers/media/i2c/soc_camera/imx074.c +++ b/drivers/media/i2c/soc_camera/imx074.c @@ -451,7 +451,9 @@ static int imx074_probe(struct i2c_client *client, if (ret < 0) goto eprobe; - return v4l2_async_register_subdev(&priv->subdev); + ret = v4l2_async_register_subdev(&priv->subdev); + if (!ret) + return 0; epwrinit: eprobe: diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index e968c3fdbd9e..bc74224503e7 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c @@ -371,7 +371,7 @@ static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code, alt->com13 = OV9640_COM13_RGB_AVG; alt->com15 = OV9640_COM15_RGB_565; break; - }; + } } /* Setup registers according to resolution and color encoding */ diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index a58a8f663ffb..04139eec8c4e 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/v4l2-dv-timings.h> #include <media/v4l2-dv-timings.h> @@ -46,14 +47,10 @@ struct ths8200_state { static const struct v4l2_dv_timings_cap ths8200_timings_cap = { .type = V4L2_DV_BT_656_1120, - .bt = { - .max_width = 1920, - .max_height = 1080, - .min_pixelclock = 25000000, - .max_pixelclock = 148500000, - .standards = V4L2_DV_BT_STD_CEA861, - .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE, - }, + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1080, 25000000, 148500000, + V4L2_DV_BT_STD_CEA861, V4L2_DV_BT_CAP_PROGRESSIVE) }; static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 91f3dd4cda1b..83d85df4853a 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -35,6 +35,7 @@ #include <linux/videodev2.h> #include <linux/module.h> #include <linux/v4l2-mediabus.h> +#include <linux/of.h> #include <media/v4l2-async.h> #include <media/v4l2-device.h> diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 24a08fa7e328..912e1cccdd1c 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -29,6 +29,7 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/v4l2-dv-timings.h> #include <media/tvp7002.h> #include <media/v4l2-async.h> |