diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 116746501985..7ae0552115a8 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -2011,6 +2011,14 @@ config VIDEO_LM3646 help This is a driver for the lm3646 dual flash controllers. It controls flash, torch LEDs. + +config VIDEO_SGM3784 + tristate "SGM3784 dual flash driver support" + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on VIDEO_V4L2_SUBDEV_API + help + This is a driver for the sgm3784 dual flash controllers. It controls + flash, torch LEDs. endmenu endif # VIDEO_V4L2 diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 969234a87b02..21d1621e329d 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -136,6 +136,7 @@ obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/ obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o obj-$(CONFIG_VIDEO_LM3560) += lm3560.o obj-$(CONFIG_VIDEO_LM3646) += lm3646.o +obj-$(CONFIG_VIDEO_SGM3784) += sgm3784.o obj-$(CONFIG_VIDEO_LT6911UXC) += lt6911uxc.o obj-$(CONFIG_VIDEO_LT7911D) += lt7911d.o obj-$(CONFIG_VIDEO_LT8619C) += lt8619c.o diff --git a/drivers/media/i2c/sgm3784.c b/drivers/media/i2c/sgm3784.c index 3f5acaf2a3ad..aedbee6e0bd3 100644 --- a/drivers/media/i2c/sgm3784.c +++ b/drivers/media/i2c/sgm3784.c @@ -13,6 +13,7 @@ #include #include #include +#include #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) #define SGM3784_NAME "sgm3784" @@ -63,7 +64,7 @@ struct sgm3784_led { struct v4l2_ctrl_handler ctrls; struct v4l2_ctrl *flash_brt; struct v4l2_ctrl *torch_brt; - struct timeval timestamp; + struct __kernel_old_timeval timestamp; u32 max_flash_timeout; u32 max_flash_intensity; u32 max_torch_intensity; @@ -131,7 +132,7 @@ static int sgm3784_led_on(struct sgm3784_flash *flash, bool on) val = on ? SGM3784_ON : SGM3784_OFF; ret = sgm3784_i2c_write(flash, SGM3784_REG_ENABLE, val); - flash->leds[0].timestamp = ns_to_timeval(ktime_get_ns()); + flash->leds[0].timestamp = ns_to_kernel_old_timeval(ktime_get_ns()); flash->leds[1].timestamp = flash->leds[0].timestamp; return ret; } @@ -452,53 +453,72 @@ static int sgm3784_init_controls(struct sgm3784_flash *flash, return 0; } -static long sgm3784_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) +static void sgm3784_get_time_info(struct v4l2_subdev *sd, + struct old_timeval32 *compat_ti) { struct sgm3784_led *led = container_of(sd, struct sgm3784_led, sd); - struct timeval *t; - v4l2_dbg(1, debug, sd, - "%s: cmd 0x%x\n", __func__, cmd); + memset(compat_ti, 0, sizeof(*compat_ti)); + compat_ti->tv_sec = led->timestamp.tv_sec; + compat_ti->tv_usec = led->timestamp.tv_usec; +} - if (cmd == RK_VIDIOC_FLASH_TIMEINFO) { - t = (struct timeval *)arg; - t->tv_sec = led->timestamp.tv_sec; - t->tv_usec = led->timestamp.tv_usec; - } else { - return -EINVAL; +static long sgm3784_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + long ret = 0; + + switch (cmd) { + case RK_VIDIOC_FLASH_TIMEINFO: + sgm3784_get_time_info(sd, (struct old_timeval32 *)arg); + break; + + default: + ret = -ENOIOCTLCMD; + break; } - - return 0; + return ret; } #ifdef CONFIG_COMPAT #define RK_VIDIOC_COMPAT_FLASH_TIMEINFO \ - _IOR('V', BASE_VIDIOC_PRIVATE + 0, struct compat_timeval) + _IOR('V', BASE_VIDIOC_PRIVATE + 0, struct old_timeval32) static long sgm3784_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) { - struct timeval t; - struct compat_timeval compat_t; - struct compat_timeval __user *p32 = compat_ptr(arg); + void __user *up = compat_ptr(arg); + struct old_timeval32 *compat_t; + long ret; v4l2_dbg(1, debug, sd, "%s: cmd 0x%x\n", __func__, cmd); - if (cmd == RK_VIDIOC_COMPAT_FLASH_TIMEINFO) { - sgm3784_ioctl(sd, RK_VIDIOC_FLASH_TIMEINFO, &t); - compat_t.tv_sec = t.tv_sec; - compat_t.tv_usec = t.tv_usec; - put_user(compat_t.tv_sec, &p32->tv_sec); - put_user(compat_t.tv_usec, &p32->tv_usec); - } else { - return -EINVAL; + switch (cmd) { + case RK_VIDIOC_COMPAT_FLASH_TIMEINFO: + compat_t = kzalloc(sizeof(*compat_t), GFP_KERNEL); + if (!compat_t) { + ret = -ENOMEM; + return ret; + } + ret = sgm3784_ioctl(sd, RK_VIDIOC_FLASH_TIMEINFO, compat_t); + if (!ret) { + ret = copy_to_user(up, compat_t, sizeof(*compat_t)); + if (ret) + ret = -EFAULT; + } + kfree(compat_t); + break; + + default: + ret = -ENOIOCTLCMD; + break; } - return 0; + return ret; + } #endif