.. | .. |
---|
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 | |
---|