| .. | .. |
|---|
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
|---|
| 2 | 2 | // Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. |
|---|
| 3 | +/* |
|---|
| 4 | + * V0.0X01.0X01 fix get wrong time info issue. |
|---|
| 5 | + */ |
|---|
| 3 | 6 | |
|---|
| 4 | 7 | #include <linux/delay.h> |
|---|
| 5 | 8 | #include <linux/gpio/consumer.h> |
|---|
| .. | .. |
|---|
| 13 | 16 | #include <linux/version.h> |
|---|
| 14 | 17 | #include <media/v4l2-ctrls.h> |
|---|
| 15 | 18 | #include <media/v4l2-device.h> |
|---|
| 19 | +#include <linux/compat.h> |
|---|
| 16 | 20 | |
|---|
| 17 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) |
|---|
| 21 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) |
|---|
| 18 | 22 | #define SGM3784_NAME "sgm3784" |
|---|
| 19 | 23 | |
|---|
| 20 | 24 | #define SGM3784_REG_ID 0x00 |
|---|
| .. | .. |
|---|
| 63 | 67 | struct v4l2_ctrl_handler ctrls; |
|---|
| 64 | 68 | struct v4l2_ctrl *flash_brt; |
|---|
| 65 | 69 | struct v4l2_ctrl *torch_brt; |
|---|
| 66 | | - struct timeval timestamp; |
|---|
| 70 | + struct __kernel_old_timeval timestamp; |
|---|
| 67 | 71 | u32 max_flash_timeout; |
|---|
| 68 | 72 | u32 max_flash_intensity; |
|---|
| 69 | 73 | u32 max_torch_intensity; |
|---|
| .. | .. |
|---|
| 131 | 135 | |
|---|
| 132 | 136 | val = on ? SGM3784_ON : SGM3784_OFF; |
|---|
| 133 | 137 | ret = sgm3784_i2c_write(flash, SGM3784_REG_ENABLE, val); |
|---|
| 134 | | - flash->leds[0].timestamp = ns_to_timeval(ktime_get_ns()); |
|---|
| 138 | + flash->leds[0].timestamp = ns_to_kernel_old_timeval(ktime_get_ns()); |
|---|
| 135 | 139 | flash->leds[1].timestamp = flash->leds[0].timestamp; |
|---|
| 136 | 140 | return ret; |
|---|
| 137 | 141 | } |
|---|
| .. | .. |
|---|
| 452 | 456 | return 0; |
|---|
| 453 | 457 | } |
|---|
| 454 | 458 | |
|---|
| 455 | | -static long sgm3784_ioctl(struct v4l2_subdev *sd, |
|---|
| 456 | | - unsigned int cmd, void *arg) |
|---|
| 459 | +static void sgm3784_get_time_info(struct v4l2_subdev *sd, |
|---|
| 460 | + struct __kernel_old_timeval *ti) |
|---|
| 457 | 461 | { |
|---|
| 458 | 462 | struct sgm3784_led *led = |
|---|
| 459 | 463 | container_of(sd, struct sgm3784_led, sd); |
|---|
| 460 | | - struct timeval *t; |
|---|
| 461 | 464 | |
|---|
| 465 | + memset(ti, 0, sizeof(*ti)); |
|---|
| 466 | + ti->tv_sec = led->timestamp.tv_sec; |
|---|
| 467 | + ti->tv_usec = led->timestamp.tv_usec; |
|---|
| 462 | 468 | v4l2_dbg(1, debug, sd, |
|---|
| 463 | | - "%s: cmd 0x%x\n", __func__, cmd); |
|---|
| 469 | + "%s: tv_sec:%ld, tv_usec:%ld\n", __func__, ti->tv_sec, ti->tv_usec); |
|---|
| 470 | +} |
|---|
| 464 | 471 | |
|---|
| 465 | | - if (cmd == RK_VIDIOC_FLASH_TIMEINFO) { |
|---|
| 466 | | - t = (struct timeval *)arg; |
|---|
| 467 | | - t->tv_sec = led->timestamp.tv_sec; |
|---|
| 468 | | - t->tv_usec = led->timestamp.tv_usec; |
|---|
| 469 | | - } else { |
|---|
| 470 | | - return -EINVAL; |
|---|
| 472 | +static long sgm3784_ioctl(struct v4l2_subdev *sd, |
|---|
| 473 | + unsigned int cmd, void *arg) |
|---|
| 474 | +{ |
|---|
| 475 | + long ret = 0; |
|---|
| 476 | + |
|---|
| 477 | + switch (cmd) { |
|---|
| 478 | + case RK_VIDIOC_FLASH_TIMEINFO: |
|---|
| 479 | + sgm3784_get_time_info(sd, (struct __kernel_old_timeval *)arg); |
|---|
| 480 | + break; |
|---|
| 481 | + |
|---|
| 482 | + default: |
|---|
| 483 | + ret = -ENOIOCTLCMD; |
|---|
| 484 | + break; |
|---|
| 471 | 485 | } |
|---|
| 472 | | - |
|---|
| 473 | | - return 0; |
|---|
| 486 | + return ret; |
|---|
| 474 | 487 | } |
|---|
| 475 | 488 | |
|---|
| 476 | 489 | #ifdef CONFIG_COMPAT |
|---|
| 477 | 490 | #define RK_VIDIOC_COMPAT_FLASH_TIMEINFO \ |
|---|
| 478 | | - _IOR('V', BASE_VIDIOC_PRIVATE + 0, struct compat_timeval) |
|---|
| 491 | + _IOR('V', BASE_VIDIOC_PRIVATE + 0, struct old_timeval32) |
|---|
| 479 | 492 | |
|---|
| 480 | 493 | static long sgm3784_compat_ioctl32(struct v4l2_subdev *sd, |
|---|
| 481 | 494 | unsigned int cmd, |
|---|
| 482 | 495 | unsigned long arg) |
|---|
| 483 | 496 | { |
|---|
| 484 | | - struct timeval t; |
|---|
| 485 | | - struct compat_timeval compat_t; |
|---|
| 486 | | - struct compat_timeval __user *p32 = compat_ptr(arg); |
|---|
| 497 | + void __user *up = compat_ptr(arg); |
|---|
| 498 | + struct old_timeval32 *compat_t; |
|---|
| 499 | + long ret; |
|---|
| 500 | + struct __kernel_old_timeval t; |
|---|
| 487 | 501 | |
|---|
| 488 | 502 | v4l2_dbg(1, debug, sd, |
|---|
| 489 | 503 | "%s: cmd 0x%x\n", __func__, cmd); |
|---|
| 490 | 504 | |
|---|
| 491 | | - if (cmd == RK_VIDIOC_COMPAT_FLASH_TIMEINFO) { |
|---|
| 492 | | - sgm3784_ioctl(sd, RK_VIDIOC_FLASH_TIMEINFO, &t); |
|---|
| 493 | | - compat_t.tv_sec = t.tv_sec; |
|---|
| 494 | | - compat_t.tv_usec = t.tv_usec; |
|---|
| 495 | | - put_user(compat_t.tv_sec, &p32->tv_sec); |
|---|
| 496 | | - put_user(compat_t.tv_usec, &p32->tv_usec); |
|---|
| 497 | | - } else { |
|---|
| 498 | | - return -EINVAL; |
|---|
| 505 | + switch (cmd) { |
|---|
| 506 | + case RK_VIDIOC_COMPAT_FLASH_TIMEINFO: |
|---|
| 507 | + compat_t = kzalloc(sizeof(*compat_t), GFP_KERNEL); |
|---|
| 508 | + if (!compat_t) { |
|---|
| 509 | + ret = -ENOMEM; |
|---|
| 510 | + return ret; |
|---|
| 511 | + } |
|---|
| 512 | + ret = sgm3784_ioctl(sd, RK_VIDIOC_FLASH_TIMEINFO, &t); |
|---|
| 513 | + if (!ret) { |
|---|
| 514 | + compat_t->tv_sec = t.tv_sec; |
|---|
| 515 | + compat_t->tv_usec = t.tv_usec; |
|---|
| 516 | + ret = copy_to_user(up, compat_t, sizeof(*compat_t)); |
|---|
| 517 | + if (ret) |
|---|
| 518 | + ret = -EFAULT; |
|---|
| 519 | + } |
|---|
| 520 | + kfree(compat_t); |
|---|
| 521 | + break; |
|---|
| 522 | + |
|---|
| 523 | + default: |
|---|
| 524 | + ret = -ENOIOCTLCMD; |
|---|
| 525 | + break; |
|---|
| 499 | 526 | } |
|---|
| 500 | 527 | |
|---|
| 501 | | - return 0; |
|---|
| 528 | + return ret; |
|---|
| 529 | + |
|---|
| 502 | 530 | } |
|---|
| 503 | 531 | #endif |
|---|
| 504 | 532 | |
|---|