.. | .. |
---|
3 | 3 | * jaguar1 driver |
---|
4 | 4 | * V0.0X01.0X00 first version. |
---|
5 | 5 | * V0.0X01.0X01 fix kernel5.10 compile error. |
---|
| 6 | + * V0.0X01.0X02 add workqueue to detect ahd state. |
---|
6 | 7 | * |
---|
7 | 8 | */ |
---|
8 | 9 | |
---|
.. | .. |
---|
41 | 42 | #include "jaguar1_drv.h" |
---|
42 | 43 | #include "jaguar1_v4l2.h" |
---|
43 | 44 | |
---|
44 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) |
---|
| 45 | +#define WORK_QUEUE |
---|
| 46 | + |
---|
| 47 | +#ifdef WORK_QUEUE |
---|
| 48 | +#include <linux/workqueue.h> |
---|
| 49 | + |
---|
| 50 | +struct sensor_state_check_work { |
---|
| 51 | + struct workqueue_struct *state_check_wq; |
---|
| 52 | + struct delayed_work d_work; |
---|
| 53 | +}; |
---|
| 54 | + |
---|
| 55 | +#endif |
---|
| 56 | + |
---|
| 57 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2) |
---|
45 | 58 | |
---|
46 | 59 | #ifndef V4L2_CID_DIGITAL_GAIN |
---|
47 | 60 | #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN |
---|
.. | .. |
---|
104 | 117 | unsigned int height; |
---|
105 | 118 | }; |
---|
106 | 119 | |
---|
| 120 | +enum jaguar1_hot_plug_state { |
---|
| 121 | + PLUG_IN = 0, |
---|
| 122 | + PLUG_OUT, |
---|
| 123 | + PLUG_STATE_MAX, |
---|
| 124 | +}; |
---|
| 125 | + |
---|
107 | 126 | struct jaguar1 { |
---|
108 | 127 | struct i2c_client *client; |
---|
109 | 128 | struct clk *xvclk; |
---|
.. | .. |
---|
134 | 153 | const struct jaguar1_framesize *frame_size; |
---|
135 | 154 | int streaming; |
---|
136 | 155 | struct jaguar1_default_rect defrect; |
---|
| 156 | +#ifdef WORK_QUEUE |
---|
| 157 | + struct sensor_state_check_work plug_state_check; |
---|
| 158 | + u8 cur_detect_status; |
---|
| 159 | + u8 last_detect_status; |
---|
| 160 | + u64 timestamp0; |
---|
| 161 | + u64 timestamp1; |
---|
| 162 | +#endif |
---|
| 163 | + bool hot_plug; |
---|
| 164 | + u8 is_reset; |
---|
| 165 | + struct semaphore reg_sem; |
---|
137 | 166 | }; |
---|
138 | 167 | |
---|
139 | 168 | #define to_jaguar1(sd) container_of(sd, struct jaguar1, subdev) |
---|
.. | .. |
---|
212 | 241 | static const s64 link_freq_menu_items[] = { |
---|
213 | 242 | JAGUAR1_LINK_FREQ |
---|
214 | 243 | }; |
---|
| 244 | + |
---|
| 245 | +/* sensor register write */ |
---|
| 246 | +static int jaguar1_write(struct i2c_client *client, u8 reg, u8 val) |
---|
| 247 | +{ |
---|
| 248 | + struct i2c_msg msg; |
---|
| 249 | + u8 buf[2]; |
---|
| 250 | + int ret; |
---|
| 251 | + |
---|
| 252 | + dev_dbg(&client->dev, "write reg(0x%x val:0x%x)!\n", reg, val); |
---|
| 253 | + buf[0] = reg & 0xFF; |
---|
| 254 | + buf[1] = val; |
---|
| 255 | + |
---|
| 256 | + msg.addr = client->addr; |
---|
| 257 | + msg.flags = client->flags; |
---|
| 258 | + msg.buf = buf; |
---|
| 259 | + msg.len = sizeof(buf); |
---|
| 260 | + |
---|
| 261 | + ret = i2c_transfer(client->adapter, &msg, 1); |
---|
| 262 | + if (ret >= 0) |
---|
| 263 | + return 0; |
---|
| 264 | + |
---|
| 265 | + dev_err(&client->dev, |
---|
| 266 | + "jaguar1 write reg(0x%x val:0x%x) failed !\n", reg, val); |
---|
| 267 | + |
---|
| 268 | + return ret; |
---|
| 269 | +} |
---|
| 270 | + |
---|
| 271 | +/* sensor register read */ |
---|
| 272 | +static int jaguar1_read(struct i2c_client *client, u8 reg, u8 *val) |
---|
| 273 | +{ |
---|
| 274 | + struct i2c_msg msg[2]; |
---|
| 275 | + u8 buf[1]; |
---|
| 276 | + int ret; |
---|
| 277 | + |
---|
| 278 | + buf[0] = reg & 0xFF; |
---|
| 279 | + |
---|
| 280 | + msg[0].addr = client->addr; |
---|
| 281 | + msg[0].flags = client->flags; |
---|
| 282 | + msg[0].buf = buf; |
---|
| 283 | + msg[0].len = sizeof(buf); |
---|
| 284 | + |
---|
| 285 | + msg[1].addr = client->addr; |
---|
| 286 | + msg[1].flags = client->flags | I2C_M_RD; |
---|
| 287 | + msg[1].buf = buf; |
---|
| 288 | + msg[1].len = 1; |
---|
| 289 | + |
---|
| 290 | + ret = i2c_transfer(client->adapter, msg, 2); |
---|
| 291 | + if (ret >= 0) { |
---|
| 292 | + *val = buf[0]; |
---|
| 293 | + return 0; |
---|
| 294 | + } |
---|
| 295 | + |
---|
| 296 | + dev_err(&client->dev, "jaguar1 read reg(0x%x) failed !\n", reg); |
---|
| 297 | + |
---|
| 298 | + return ret; |
---|
| 299 | +} |
---|
| 300 | + |
---|
215 | 301 | static int __jaguar1_power_on(struct jaguar1 *jaguar1) |
---|
216 | 302 | { |
---|
217 | 303 | u32 i; |
---|
.. | .. |
---|
340 | 426 | struct jaguar1 *jaguar1 = to_jaguar1(sd); |
---|
341 | 427 | int ret = 0; |
---|
342 | 428 | |
---|
343 | | - dev_dbg(&client->dev, "%s: on %d\n", __func__, on); |
---|
| 429 | + dev_info(&client->dev, "%s: on %d\n", __func__, on); |
---|
344 | 430 | mutex_lock(&jaguar1->mutex); |
---|
345 | 431 | |
---|
346 | 432 | /* If the power state is not modified - no work to do. */ |
---|
.. | .. |
---|
351 | 437 | ret = __jaguar1_power_on(jaguar1); |
---|
352 | 438 | if (ret < 0) |
---|
353 | 439 | goto exit; |
---|
354 | | - |
---|
355 | 440 | jaguar1->power_on = true; |
---|
| 441 | + |
---|
356 | 442 | } else { |
---|
357 | 443 | __jaguar1_power_off(jaguar1); |
---|
358 | 444 | jaguar1->power_on = false; |
---|
| 445 | + |
---|
359 | 446 | } |
---|
360 | 447 | |
---|
361 | 448 | exit: |
---|
.. | .. |
---|
430 | 517 | format->field = match->field; |
---|
431 | 518 | } |
---|
432 | 519 | |
---|
| 520 | +static inline bool jaguar1_no_signal(struct v4l2_subdev *sd, u8 *novid); |
---|
433 | 521 | static int jaguar1_stream(struct v4l2_subdev *sd, int on) |
---|
434 | 522 | { |
---|
435 | 523 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
---|
.. | .. |
---|
438 | 526 | enum NC_VIVO_CH_FORMATDEF fmt_idx; |
---|
439 | 527 | int ch; |
---|
440 | 528 | |
---|
441 | | - dev_dbg(&client->dev, "%s: on %d\n", __func__, on); |
---|
| 529 | + dev_info(&client->dev, "%s: on %d\n", __func__, on); |
---|
442 | 530 | mutex_lock(&jaguar1->mutex); |
---|
443 | 531 | on = !!on; |
---|
444 | 532 | |
---|
.. | .. |
---|
455 | 543 | video_init.ch_param[ch].interface = YUV_422; |
---|
456 | 544 | } |
---|
457 | 545 | jaguar1_start(&video_init); |
---|
| 546 | +#ifdef WORK_QUEUE |
---|
| 547 | + jaguar1->hot_plug = false; |
---|
| 548 | + jaguar1->is_reset = 0; |
---|
| 549 | + usleep_range(20000, 21000); |
---|
| 550 | + /* get power on state first*/ |
---|
| 551 | + jaguar1_no_signal(sd, &jaguar1->last_detect_status); |
---|
| 552 | + /* check hot plug state */ |
---|
| 553 | + if (jaguar1->plug_state_check.state_check_wq) { |
---|
| 554 | + dev_info(&client->dev, "%s queue_delayed_work 1000ms", __func__); |
---|
| 555 | + queue_delayed_work(jaguar1->plug_state_check.state_check_wq, |
---|
| 556 | + &jaguar1->plug_state_check.d_work, |
---|
| 557 | + msecs_to_jiffies(1000)); |
---|
| 558 | + } |
---|
| 559 | + jaguar1->timestamp0 = ktime_get_ns(); |
---|
| 560 | +#endif |
---|
458 | 561 | } else { |
---|
459 | 562 | jaguar1_stop(); |
---|
| 563 | +#ifdef WORK_QUEUE |
---|
| 564 | + jaguar1->timestamp1 = ktime_get_ns(); |
---|
| 565 | + /* if stream off & on interval too short, do repower */ |
---|
| 566 | + if (div_u64((jaguar1->timestamp1 - jaguar1->timestamp0), 1000000) < 1200) { |
---|
| 567 | + dev_info(&client->dev, "stream on/off too short, do power off & on!"); |
---|
| 568 | + __jaguar1_power_off(jaguar1); |
---|
| 569 | + usleep_range(40000, 41000); |
---|
| 570 | + __jaguar1_power_on(jaguar1); |
---|
| 571 | + } |
---|
| 572 | + cancel_delayed_work_sync(&jaguar1->plug_state_check.d_work); |
---|
| 573 | + dev_info(&client->dev, "cancle_queue_delayed_work"); |
---|
| 574 | +#endif |
---|
460 | 575 | } |
---|
461 | 576 | |
---|
462 | 577 | jaguar1->streaming = on; |
---|
.. | .. |
---|
505 | 620 | return 0; |
---|
506 | 621 | } |
---|
507 | 622 | |
---|
| 623 | +/* indicate N4 no signal channel */ |
---|
| 624 | +static inline bool jaguar1_no_signal(struct v4l2_subdev *sd, u8 *novid) |
---|
| 625 | +{ |
---|
| 626 | + struct jaguar1 *jaguar1 = to_jaguar1(sd); |
---|
| 627 | + struct i2c_client *client = jaguar1->client; |
---|
| 628 | + u8 videoloss = 0; |
---|
| 629 | + u8 temp = 0; |
---|
| 630 | + int ch, ret; |
---|
| 631 | + bool no_signal = false; |
---|
| 632 | + |
---|
| 633 | + jaguar1_write(client, 0xff, 0x00); |
---|
| 634 | + for (ch = 0 ; ch < 4; ch++) { |
---|
| 635 | + ret = jaguar1_read(client, 0xa4 + ch, &temp); |
---|
| 636 | + if (ret < 0) |
---|
| 637 | + dev_err(&client->dev, "Failed to read videoloss state!\n"); |
---|
| 638 | + videoloss |= (temp << ch); |
---|
| 639 | + } |
---|
| 640 | + *novid = videoloss; |
---|
| 641 | + dev_dbg(&client->dev, "%s: video loss status:0x%x.\n", __func__, videoloss); |
---|
| 642 | + if (videoloss == 0xf) { |
---|
| 643 | + dev_dbg(&client->dev, "%s: all channels No Video detected.\n", __func__); |
---|
| 644 | + no_signal = true; |
---|
| 645 | + } else { |
---|
| 646 | + dev_dbg(&client->dev, "%s: channel has some video detection.\n", __func__); |
---|
| 647 | + no_signal = false; |
---|
| 648 | + } |
---|
| 649 | + return no_signal; |
---|
| 650 | +} |
---|
| 651 | + |
---|
| 652 | +/* indicate N4 channel locked status */ |
---|
| 653 | +static inline bool jaguar1_sync(struct v4l2_subdev *sd, u8 *lock_st) |
---|
| 654 | +{ |
---|
| 655 | + struct i2c_client *client = v4l2_get_subdevdata(sd); |
---|
| 656 | + u8 video_lock_status = 0; |
---|
| 657 | + u8 temp = 0; |
---|
| 658 | + int ch, ret; |
---|
| 659 | + bool has_sync = false; |
---|
| 660 | + |
---|
| 661 | + jaguar1_write(client, 0xff, 0x00); |
---|
| 662 | + for (ch = 0 ; ch < 4; ch++) { |
---|
| 663 | + ret = jaguar1_read(client, 0xd0 + ch, &temp); |
---|
| 664 | + if (ret < 0) |
---|
| 665 | + dev_err(&client->dev, "Failed to read LOCK status!\n"); |
---|
| 666 | + video_lock_status |= (temp << ch); |
---|
| 667 | + } |
---|
| 668 | + |
---|
| 669 | + dev_dbg(&client->dev, "%s: video AGC LOCK status:0x%x.\n", |
---|
| 670 | + __func__, video_lock_status); |
---|
| 671 | + *lock_st = video_lock_status; |
---|
| 672 | + if (video_lock_status) { |
---|
| 673 | + dev_dbg(&client->dev, "%s: channel has AGC LOCK.\n", __func__); |
---|
| 674 | + has_sync = true; |
---|
| 675 | + } else { |
---|
| 676 | + dev_dbg(&client->dev, "%s: channel has no AGC LOCK.\n", __func__); |
---|
| 677 | + has_sync = false; |
---|
| 678 | + } |
---|
| 679 | + return has_sync; |
---|
| 680 | +} |
---|
| 681 | + |
---|
| 682 | +#ifdef WORK_QUEUE |
---|
| 683 | +static void jaguar1_plug_state_check_work(struct work_struct *work) |
---|
| 684 | +{ |
---|
| 685 | + struct sensor_state_check_work *params_check = |
---|
| 686 | + container_of(work, struct sensor_state_check_work, d_work.work); |
---|
| 687 | + struct jaguar1 *jaguar1 = |
---|
| 688 | + container_of(params_check, struct jaguar1, plug_state_check); |
---|
| 689 | + struct i2c_client *client = jaguar1->client; |
---|
| 690 | + struct v4l2_subdev *sd = &jaguar1->subdev; |
---|
| 691 | + u8 novid_status = 0x00; |
---|
| 692 | + u8 sync_status = 0x00; |
---|
| 693 | + |
---|
| 694 | + down(&jaguar1->reg_sem); |
---|
| 695 | + jaguar1_no_signal(sd, &novid_status); |
---|
| 696 | + jaguar1_sync(sd, &sync_status); |
---|
| 697 | + up(&jaguar1->reg_sem); |
---|
| 698 | + jaguar1->cur_detect_status = novid_status; |
---|
| 699 | + |
---|
| 700 | + /* detect state change to determine is there has plug motion */ |
---|
| 701 | + novid_status = jaguar1->cur_detect_status ^ jaguar1->last_detect_status; |
---|
| 702 | + if (novid_status) |
---|
| 703 | + jaguar1->hot_plug = true; |
---|
| 704 | + else |
---|
| 705 | + jaguar1->hot_plug = false; |
---|
| 706 | + jaguar1->last_detect_status = jaguar1->cur_detect_status; |
---|
| 707 | + |
---|
| 708 | + if (jaguar1->hot_plug) |
---|
| 709 | + dev_info(&client->dev, "%s has plug motion? (%s)", __func__, |
---|
| 710 | + jaguar1->hot_plug ? "true" : "false"); |
---|
| 711 | + if (jaguar1->hot_plug) { |
---|
| 712 | + dev_dbg(&client->dev, "queue_delayed_work 1500ms, if has hot plug motion."); |
---|
| 713 | + queue_delayed_work(jaguar1->plug_state_check.state_check_wq, |
---|
| 714 | + &jaguar1->plug_state_check.d_work, msecs_to_jiffies(1500)); |
---|
| 715 | + jaguar1_write(client, 0xFF, 0x20); |
---|
| 716 | + jaguar1_write(client, 0x00, 0x00); |
---|
| 717 | + //jaguar1_write(client, 0x00, (sync_status << 4) | sync_status); |
---|
| 718 | + usleep_range(3000, 5000); |
---|
| 719 | + jaguar1_write(client, 0x00, 0xFF); |
---|
| 720 | + } else { |
---|
| 721 | + dev_dbg(&client->dev, "queue_delayed_work 100ms, if no hot plug motion."); |
---|
| 722 | + queue_delayed_work(jaguar1->plug_state_check.state_check_wq, |
---|
| 723 | + &jaguar1->plug_state_check.d_work, msecs_to_jiffies(100)); |
---|
| 724 | + } |
---|
| 725 | +} |
---|
| 726 | +#endif |
---|
| 727 | + |
---|
| 728 | +static int jaguar1_g_input_status(struct v4l2_subdev *sd, u32 *status) |
---|
| 729 | +{ |
---|
| 730 | + struct i2c_client *client = v4l2_get_subdevdata(sd); |
---|
| 731 | + struct jaguar1 *jaguar1 = to_jaguar1(sd); |
---|
| 732 | + int ret; |
---|
| 733 | + u8 temp_novid; |
---|
| 734 | + u8 temp_lock_st; |
---|
| 735 | + |
---|
| 736 | + if (!jaguar1->power_on) { |
---|
| 737 | + ret = __jaguar1_power_on(jaguar1); |
---|
| 738 | + if (ret < 0) |
---|
| 739 | + goto exit; |
---|
| 740 | + usleep_range(40000, 50000); |
---|
| 741 | + jaguar1->power_on = true; |
---|
| 742 | + } |
---|
| 743 | + |
---|
| 744 | + *status = 0; |
---|
| 745 | + *status |= jaguar1_no_signal(sd, &temp_novid) ? V4L2_IN_ST_NO_SIGNAL : 0; |
---|
| 746 | + *status |= jaguar1_sync(sd, &temp_lock_st) ? 0 : V4L2_IN_ST_NO_SYNC; |
---|
| 747 | + |
---|
| 748 | + dev_info(&client->dev, "%s: status = 0x%x\n", __func__, *status); |
---|
| 749 | + |
---|
| 750 | +exit: |
---|
| 751 | + return 0; |
---|
| 752 | +} |
---|
| 753 | + |
---|
508 | 754 | static int jaguar1_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, |
---|
509 | 755 | struct v4l2_mbus_config *cfg) |
---|
510 | 756 | { |
---|
511 | 757 | cfg->type = V4L2_MBUS_CSI2_DPHY; |
---|
512 | 758 | cfg->flags = V4L2_MBUS_CSI2_4_LANE | |
---|
513 | | - V4L2_MBUS_CSI2_CHANNELS; |
---|
| 759 | + V4L2_MBUS_CSI2_CHANNELS | |
---|
| 760 | + V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
---|
514 | 761 | |
---|
515 | 762 | return 0; |
---|
516 | 763 | } |
---|
.. | .. |
---|
660 | 907 | strlcpy(inf->base.lens, jaguar1->len_name, sizeof(inf->base.lens)); |
---|
661 | 908 | } |
---|
662 | 909 | |
---|
| 910 | +static void jaguar1_get_vicap_rst_inf(struct jaguar1 *jaguar1, |
---|
| 911 | + struct rkmodule_vicap_reset_info *rst_info) |
---|
| 912 | +{ |
---|
| 913 | + struct i2c_client *client = jaguar1->client; |
---|
| 914 | + |
---|
| 915 | + rst_info->is_reset = jaguar1->hot_plug; |
---|
| 916 | + jaguar1->hot_plug = false; |
---|
| 917 | + rst_info->src = RKCIF_RESET_SRC_ERR_HOTPLUG; |
---|
| 918 | + if (rst_info->is_reset) |
---|
| 919 | + dev_info(&client->dev, "%s: rst_info->is_reset:%d.\n", |
---|
| 920 | + __func__, rst_info->is_reset); |
---|
| 921 | +} |
---|
| 922 | + |
---|
| 923 | +static void jaguar1_set_vicap_rst_inf(struct jaguar1 *jaguar1, |
---|
| 924 | + struct rkmodule_vicap_reset_info rst_info) |
---|
| 925 | +{ |
---|
| 926 | + jaguar1->is_reset = rst_info.is_reset; |
---|
| 927 | + jaguar1->hot_plug = rst_info.is_reset; |
---|
| 928 | +} |
---|
| 929 | + |
---|
| 930 | +static void jaguar1_set_streaming(struct jaguar1 *jaguar1, int on) |
---|
| 931 | +{ |
---|
| 932 | + struct i2c_client *client = jaguar1->client; |
---|
| 933 | + |
---|
| 934 | + |
---|
| 935 | + dev_info(&client->dev, "%s: on: %d\n", __func__, on); |
---|
| 936 | + down(&jaguar1->reg_sem); |
---|
| 937 | + if (on) { |
---|
| 938 | + /* enter mipi clk normal operation */ |
---|
| 939 | + jaguar1_write(client, 0xff, 0x21); |
---|
| 940 | + jaguar1_write(client, 0x46, 0x00); |
---|
| 941 | + } else { |
---|
| 942 | + /* enter mipi clk powerdown */ |
---|
| 943 | + jaguar1_write(client, 0xff, 0x21); |
---|
| 944 | + jaguar1_write(client, 0x46, 0x01); |
---|
| 945 | + } |
---|
| 946 | + up(&jaguar1->reg_sem); |
---|
| 947 | +} |
---|
| 948 | + |
---|
663 | 949 | static long jaguar1_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
---|
664 | 950 | { |
---|
665 | 951 | struct jaguar1 *jaguar1 = to_jaguar1(sd); |
---|
666 | 952 | long ret = 0; |
---|
| 953 | + u32 stream = 0; |
---|
667 | 954 | |
---|
668 | 955 | switch (cmd) { |
---|
669 | 956 | case RKMODULE_GET_MODULE_INFO: |
---|
670 | 957 | jaguar1_get_module_inf(jaguar1, (struct rkmodule_inf *)arg); |
---|
671 | 958 | break; |
---|
| 959 | + case RKMODULE_GET_VICAP_RST_INFO: |
---|
| 960 | + jaguar1_get_vicap_rst_inf(jaguar1, (struct rkmodule_vicap_reset_info *)arg); |
---|
| 961 | + break; |
---|
| 962 | + case RKMODULE_SET_VICAP_RST_INFO: |
---|
| 963 | + jaguar1_set_vicap_rst_inf(jaguar1, *(struct rkmodule_vicap_reset_info *)arg); |
---|
| 964 | + break; |
---|
672 | 965 | case RKMODULE_GET_START_STREAM_SEQ: |
---|
673 | 966 | *(int *)arg = RKMODULE_START_STREAM_FRONT; |
---|
| 967 | + break; |
---|
| 968 | + case RKMODULE_SET_QUICK_STREAM: |
---|
| 969 | + stream = *((u32 *)arg); |
---|
| 970 | + jaguar1_set_streaming(jaguar1, !!stream); |
---|
674 | 971 | break; |
---|
675 | 972 | default: |
---|
676 | 973 | ret = -ENOTTY; |
---|
.. | .. |
---|
687 | 984 | void __user *up = compat_ptr(arg); |
---|
688 | 985 | struct rkmodule_inf *inf; |
---|
689 | 986 | struct rkmodule_awb_cfg *cfg; |
---|
| 987 | + struct rkmodule_vicap_reset_info *vicap_rst_inf; |
---|
690 | 988 | long ret; |
---|
691 | 989 | int *seq; |
---|
| 990 | + u32 stream = 0; |
---|
692 | 991 | |
---|
693 | 992 | switch (cmd) { |
---|
694 | 993 | case RKMODULE_GET_MODULE_INFO: |
---|
.. | .. |
---|
720 | 1019 | ret = -EFAULT; |
---|
721 | 1020 | kfree(cfg); |
---|
722 | 1021 | break; |
---|
| 1022 | + case RKMODULE_GET_VICAP_RST_INFO: |
---|
| 1023 | + vicap_rst_inf = kzalloc(sizeof(*vicap_rst_inf), GFP_KERNEL); |
---|
| 1024 | + if (!vicap_rst_inf) { |
---|
| 1025 | + ret = -ENOMEM; |
---|
| 1026 | + return ret; |
---|
| 1027 | + } |
---|
| 1028 | + |
---|
| 1029 | + ret = jaguar1_ioctl(sd, cmd, vicap_rst_inf); |
---|
| 1030 | + if (!ret) { |
---|
| 1031 | + ret = copy_to_user(up, vicap_rst_inf, sizeof(*vicap_rst_inf)); |
---|
| 1032 | + if (ret) |
---|
| 1033 | + ret = -EFAULT; |
---|
| 1034 | + } |
---|
| 1035 | + kfree(vicap_rst_inf); |
---|
| 1036 | + break; |
---|
| 1037 | + case RKMODULE_SET_VICAP_RST_INFO: |
---|
| 1038 | + vicap_rst_inf = kzalloc(sizeof(*vicap_rst_inf), GFP_KERNEL); |
---|
| 1039 | + if (!vicap_rst_inf) { |
---|
| 1040 | + ret = -ENOMEM; |
---|
| 1041 | + return ret; |
---|
| 1042 | + } |
---|
| 1043 | + |
---|
| 1044 | + ret = copy_from_user(vicap_rst_inf, up, sizeof(*vicap_rst_inf)); |
---|
| 1045 | + if (!ret) |
---|
| 1046 | + ret = jaguar1_ioctl(sd, cmd, vicap_rst_inf); |
---|
| 1047 | + else |
---|
| 1048 | + ret = -EFAULT; |
---|
| 1049 | + kfree(vicap_rst_inf); |
---|
| 1050 | + break; |
---|
723 | 1051 | case RKMODULE_GET_START_STREAM_SEQ: |
---|
724 | 1052 | seq = kzalloc(sizeof(*seq), GFP_KERNEL); |
---|
725 | 1053 | if (!seq) { |
---|
.. | .. |
---|
734 | 1062 | ret = -EFAULT; |
---|
735 | 1063 | } |
---|
736 | 1064 | kfree(seq); |
---|
| 1065 | + break; |
---|
| 1066 | + case RKMODULE_SET_QUICK_STREAM: |
---|
| 1067 | + ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
| 1068 | + if (!ret) |
---|
| 1069 | + ret = jaguar1_ioctl(sd, cmd, &stream); |
---|
| 1070 | + else |
---|
| 1071 | + ret = -EFAULT; |
---|
737 | 1072 | break; |
---|
738 | 1073 | default: |
---|
739 | 1074 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
770 | 1105 | }; |
---|
771 | 1106 | |
---|
772 | 1107 | static const struct v4l2_subdev_video_ops jaguar1_video_ops = { |
---|
| 1108 | + .g_input_status = jaguar1_g_input_status, |
---|
773 | 1109 | .s_stream = jaguar1_stream, |
---|
774 | 1110 | .g_frame_interval = jaguar1_g_frame_interval, |
---|
775 | 1111 | }; |
---|
.. | .. |
---|
984 | 1320 | } |
---|
985 | 1321 | |
---|
986 | 1322 | __jaguar1_power_on(jaguar1); |
---|
987 | | - ret = jaguar1_init(i2c_adapter_id(client->adapter)); |
---|
| 1323 | + ret |= jaguar1_init(i2c_adapter_id(client->adapter)); |
---|
988 | 1324 | if (ret) { |
---|
989 | 1325 | dev_err(dev, "Failed to init jaguar1\n"); |
---|
990 | 1326 | __jaguar1_power_off(jaguar1); |
---|
.. | .. |
---|
992 | 1328 | |
---|
993 | 1329 | return ret; |
---|
994 | 1330 | } |
---|
995 | | - |
---|
| 1331 | + sema_init(&jaguar1->reg_sem, 1); |
---|
996 | 1332 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API |
---|
997 | 1333 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
---|
998 | 1334 | #endif |
---|
.. | .. |
---|
1034 | 1370 | |
---|
1035 | 1371 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, |
---|
1036 | 1372 | client->addr << 1, client->adapter->name); |
---|
| 1373 | +#ifdef WORK_QUEUE |
---|
| 1374 | + /* init work_queue for state_check */ |
---|
| 1375 | + INIT_DELAYED_WORK(&jaguar1->plug_state_check.d_work, jaguar1_plug_state_check_work); |
---|
| 1376 | + jaguar1->plug_state_check.state_check_wq = |
---|
| 1377 | + create_singlethread_workqueue("jaguar1_work_queue"); |
---|
| 1378 | + if (jaguar1->plug_state_check.state_check_wq == NULL) { |
---|
| 1379 | + dev_err(dev, "%s(%d): %s create failed.\n", __func__, __LINE__, |
---|
| 1380 | + "jaguar1_work_queue"); |
---|
| 1381 | + } |
---|
| 1382 | + jaguar1->cur_detect_status = 0x0; |
---|
| 1383 | + jaguar1->last_detect_status = 0x0; |
---|
| 1384 | + jaguar1->hot_plug = false; |
---|
| 1385 | + jaguar1->is_reset = 0; |
---|
| 1386 | + |
---|
| 1387 | +#endif |
---|
| 1388 | + |
---|
1037 | 1389 | return 0; |
---|
1038 | 1390 | |
---|
1039 | 1391 | err_power_off: |
---|
.. | .. |
---|
1060 | 1412 | if (!pm_runtime_status_suspended(&client->dev)) |
---|
1061 | 1413 | __jaguar1_power_off(jaguar1); |
---|
1062 | 1414 | pm_runtime_set_suspended(&client->dev); |
---|
1063 | | - |
---|
| 1415 | +#ifdef WORK_QUEUE |
---|
| 1416 | + if (jaguar1->plug_state_check.state_check_wq != NULL) |
---|
| 1417 | + destroy_workqueue(jaguar1->plug_state_check.state_check_wq); |
---|
| 1418 | +#endif |
---|
1064 | 1419 | return 0; |
---|
1065 | 1420 | } |
---|
1066 | 1421 | |
---|