diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-05 14:55:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-05 14:55:59 -0400 |
commit | 27c053aa8d18d1fa7b83041e36bad20bcdf55514 (patch) | |
tree | c59dce17a248dd8f4757eca3823032334c626dcd /drivers/media | |
parent | a09e9a7a4b907f2dfa9bdb2b98a1828ab4b340b2 (diff) | |
parent | f66b2a1c7f2ae3fb0d5b67d07ab4f5055fd3cf16 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
"This series contains:
- Exynos s5p-mfc driver got support for VP8 encoder
- Some SoC drivers gained support for asynchronous registration
(needed for DT)
- The RC subsystem gained support for RC activity LED;
- New drivers added: a video decoder(adv7842), a video encoder
(adv7511), a new GSPCA driver (stk1135) and support for Renesas
R-Car (vsp1)
- the first SDR kernel driver: mirics msi3101. Due to some troubles
with the driver, and because the API is still under discussion, it
will be merged at staging for 3.12. Need to rework on it
- usual new boards additions, fixes, cleanups and driver
improvements"
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (242 commits)
[media] cx88: Fix regression: CX88_AUDIO_WM8775 can't be 0
[media] exynos4-is: Fix entity unregistration on error path
[media] exynos-gsc: Register v4l2 device
[media] exynos4-is: Fix fimc-lite bayer formats
[media] em28xx: fix assignment of the eeprom data
[media] hdpvr: fix iteration over uninitialized lists in hdpvr_probe()
[media] usbtv: Throw corrupted frames away
[media] usbtv: Fix deinterlacing
[media] v4l2: added missing mutex.h include to v4l2-ctrls.h
[media] DocBook: upgrade media_api DocBook version to 4.2
[media] ml86v7667: fix compile warning: 'ret' set but not used
[media] s5p-g2d: Fix registration failure
[media] media: coda: Fix DT driver data pointer for i.MX27
[media] s5p-mfc: Fix input/output format reporting
[media] v4l: vsp1: Fix mutex double lock at streamon time
[media] v4l: vsp1: Add support for RT clock
[media] v4l: vsp1: Initialize media device bus_info field
[media] davinci: vpif_capture: fix error return code in vpif_probe()
[media] davinci: vpif_display: fix error return code in vpif_probe()
[media] MAINTAINERS: add entries for adv7511 and adv7842
...
Diffstat (limited to 'drivers/media')
154 files changed, 15913 insertions, 2069 deletions
diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig index f3f5ec44e685..f953d33ee151 100644 --- a/drivers/media/common/siano/Kconfig +++ b/drivers/media/common/siano/Kconfig | |||
@@ -23,6 +23,8 @@ config SMS_SIANO_DEBUGFS | |||
23 | depends on SMS_SIANO_MDTV | 23 | depends on SMS_SIANO_MDTV |
24 | depends on DEBUG_FS | 24 | depends on DEBUG_FS |
25 | depends on SMS_USB_DRV | 25 | depends on SMS_USB_DRV |
26 | depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV | ||
27 | |||
26 | ---help--- | 28 | ---help--- |
27 | Choose Y to enable visualizing a dump of the frontend | 29 | Choose Y to enable visualizing a dump of the frontend |
28 | statistics response packets via debugfs. Currently, works | 30 | statistics response packets via debugfs. Currently, works |
diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index 086262252230..63676a8b024c 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c | |||
@@ -276,7 +276,8 @@ static void smsdvb_update_per_slices(struct smsdvb_client_t *client, | |||
276 | 276 | ||
277 | /* Legacy PER/BER */ | 277 | /* Legacy PER/BER */ |
278 | tmp = p->ets_packets * 65535; | 278 | tmp = p->ets_packets * 65535; |
279 | do_div(tmp, p->ts_packets + p->ets_packets); | 279 | if (p->ts_packets + p->ets_packets) |
280 | do_div(tmp, p->ts_packets + p->ets_packets); | ||
280 | client->legacy_per = tmp; | 281 | client->legacy_per = tmp; |
281 | } | 282 | } |
282 | 283 | ||
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 886da16e14f2..419a2d6b4349 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h | |||
@@ -369,4 +369,6 @@ | |||
369 | #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 | 369 | #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 |
370 | #define USB_PID_CPYTO_REDI_PC50A 0xa803 | 370 | #define USB_PID_CPYTO_REDI_PC50A 0xa803 |
371 | #define USB_PID_CTVDIGDUAL_V2 0xe410 | 371 | #define USB_PID_CTVDIGDUAL_V2 0xe410 |
372 | #define USB_PID_PCTV_2002E 0x025c | ||
373 | #define USB_PID_PCTV_2002E_SE 0x025d | ||
372 | #endif | 374 | #endif |
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index 856374bd3676..2c7217fb1415 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c | |||
@@ -157,7 +157,6 @@ static struct regdata mb86a20s_init2[] = { | |||
157 | { 0x45, 0x04 }, /* CN symbol 4 */ | 157 | { 0x45, 0x04 }, /* CN symbol 4 */ |
158 | { 0x48, 0x04 }, /* CN manual mode */ | 158 | { 0x48, 0x04 }, /* CN manual mode */ |
159 | 159 | ||
160 | { 0x50, 0xd5 }, { 0x51, 0x01 }, /* Serial */ | ||
161 | { 0x50, 0xd6 }, { 0x51, 0x1f }, | 160 | { 0x50, 0xd6 }, { 0x51, 0x1f }, |
162 | { 0x50, 0xd2 }, { 0x51, 0x03 }, | 161 | { 0x50, 0xd2 }, { 0x51, 0x03 }, |
163 | { 0x50, 0xd7 }, { 0x51, 0xbf }, | 162 | { 0x50, 0xd7 }, { 0x51, 0xbf }, |
@@ -1860,16 +1859,15 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) | |||
1860 | dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n", | 1859 | dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n", |
1861 | __func__, state->if_freq, (long long)pll); | 1860 | __func__, state->if_freq, (long long)pll); |
1862 | 1861 | ||
1863 | if (!state->config->is_serial) { | 1862 | if (!state->config->is_serial) |
1864 | regD5 &= ~1; | 1863 | regD5 &= ~1; |
1865 | 1864 | ||
1866 | rc = mb86a20s_writereg(state, 0x50, 0xd5); | 1865 | rc = mb86a20s_writereg(state, 0x50, 0xd5); |
1867 | if (rc < 0) | 1866 | if (rc < 0) |
1868 | goto err; | 1867 | goto err; |
1869 | rc = mb86a20s_writereg(state, 0x51, regD5); | 1868 | rc = mb86a20s_writereg(state, 0x51, regD5); |
1870 | if (rc < 0) | 1869 | if (rc < 0) |
1871 | goto err; | 1870 | goto err; |
1872 | } | ||
1873 | 1871 | ||
1874 | rc = mb86a20s_writeregdata(state, mb86a20s_init2); | 1872 | rc = mb86a20s_writeregdata(state, mb86a20s_init2); |
1875 | if (rc < 0) | 1873 | if (rc < 0) |
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index b2cd8ca51af7..d18be19c96cd 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig | |||
@@ -206,6 +206,18 @@ config VIDEO_ADV7604 | |||
206 | To compile this driver as a module, choose M here: the | 206 | To compile this driver as a module, choose M here: the |
207 | module will be called adv7604. | 207 | module will be called adv7604. |
208 | 208 | ||
209 | config VIDEO_ADV7842 | ||
210 | tristate "Analog Devices ADV7842 decoder" | ||
211 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API | ||
212 | ---help--- | ||
213 | Support for the Analog Devices ADV7842 video decoder. | ||
214 | |||
215 | This is a Analog Devices Component/Graphics/SD Digitizer | ||
216 | with 2:1 Multiplexed HDMI Receiver. | ||
217 | |||
218 | To compile this driver as a module, choose M here: the | ||
219 | module will be called adv7842. | ||
220 | |||
209 | config VIDEO_BT819 | 221 | config VIDEO_BT819 |
210 | tristate "BT819A VideoStream decoder" | 222 | tristate "BT819A VideoStream decoder" |
211 | depends on VIDEO_V4L2 && I2C | 223 | depends on VIDEO_V4L2 && I2C |
@@ -417,6 +429,17 @@ config VIDEO_ADV7393 | |||
417 | To compile this driver as a module, choose M here: the | 429 | To compile this driver as a module, choose M here: the |
418 | module will be called adv7393. | 430 | module will be called adv7393. |
419 | 431 | ||
432 | config VIDEO_ADV7511 | ||
433 | tristate "Analog Devices ADV7511 encoder" | ||
434 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API | ||
435 | ---help--- | ||
436 | Support for the Analog Devices ADV7511 video encoder. | ||
437 | |||
438 | This is a Analog Devices HDMI transmitter. | ||
439 | |||
440 | To compile this driver as a module, choose M here: the | ||
441 | module will be called adv7511. | ||
442 | |||
420 | config VIDEO_AD9389B | 443 | config VIDEO_AD9389B |
421 | tristate "Analog Devices AD9389B encoder" | 444 | tristate "Analog Devices AD9389B encoder" |
422 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API | 445 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API |
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index dc20653bb5ad..9f462df77b4a 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile | |||
@@ -26,7 +26,9 @@ obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o | |||
26 | obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o | 26 | obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o |
27 | obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o | 27 | obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o |
28 | obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o | 28 | obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o |
29 | obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o | ||
29 | obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o | 30 | obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o |
31 | obj-$(CONFIG_VIDEO_ADV7511) += adv7511.o | ||
30 | obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o | 32 | obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o |
31 | obj-$(CONFIG_VIDEO_VS6624) += vs6624.o | 33 | obj-$(CONFIG_VIDEO_VS6624) += vs6624.o |
32 | obj-$(CONFIG_VIDEO_BT819) += bt819.o | 34 | obj-$(CONFIG_VIDEO_BT819) += bt819.o |
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index ba4364dfae66..bb0c99d7a4f1 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/v4l2-dv-timings.h> | 33 | #include <linux/v4l2-dv-timings.h> |
34 | #include <media/v4l2-device.h> | 34 | #include <media/v4l2-device.h> |
35 | #include <media/v4l2-common.h> | 35 | #include <media/v4l2-common.h> |
36 | #include <media/v4l2-dv-timings.h> | ||
36 | #include <media/v4l2-ctrls.h> | 37 | #include <media/v4l2-ctrls.h> |
37 | #include <media/ad9389b.h> | 38 | #include <media/ad9389b.h> |
38 | 39 | ||
@@ -442,22 +443,11 @@ static int ad9389b_log_status(struct v4l2_subdev *sd) | |||
442 | vic_detect, vic_sent); | 443 | vic_detect, vic_sent); |
443 | } | 444 | } |
444 | } | 445 | } |
445 | if (state->dv_timings.type == V4L2_DV_BT_656_1120) { | 446 | if (state->dv_timings.type == V4L2_DV_BT_656_1120) |
446 | struct v4l2_bt_timings *bt = bt = &state->dv_timings.bt; | 447 | v4l2_print_dv_timings(sd->name, "timings: ", |
447 | u32 frame_width = bt->width + bt->hfrontporch + | 448 | &state->dv_timings, false); |
448 | bt->hsync + bt->hbackporch; | 449 | else |
449 | u32 frame_height = bt->height + bt->vfrontporch + | ||
450 | bt->vsync + bt->vbackporch; | ||
451 | u32 frame_size = frame_width * frame_height; | ||
452 | |||
453 | v4l2_info(sd, "timings: %ux%u%s%u (%ux%u). Pix freq. = %u Hz. Polarities = 0x%x\n", | ||
454 | bt->width, bt->height, bt->interlaced ? "i" : "p", | ||
455 | frame_size > 0 ? (unsigned)bt->pixelclock / frame_size : 0, | ||
456 | frame_width, frame_height, | ||
457 | (unsigned)bt->pixelclock, bt->polarities); | ||
458 | } else { | ||
459 | v4l2_info(sd, "no timings set\n"); | 450 | v4l2_info(sd, "no timings set\n"); |
460 | } | ||
461 | return 0; | 451 | return 0; |
462 | } | 452 | } |
463 | 453 | ||
@@ -636,95 +626,34 @@ static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable) | |||
636 | return 0; | 626 | return 0; |
637 | } | 627 | } |
638 | 628 | ||
639 | static const struct v4l2_dv_timings ad9389b_timings[] = { | 629 | static const struct v4l2_dv_timings_cap ad9389b_timings_cap = { |
640 | V4L2_DV_BT_CEA_720X480P59_94, | 630 | .type = V4L2_DV_BT_656_1120, |
641 | V4L2_DV_BT_CEA_720X576P50, | 631 | .bt = { |
642 | V4L2_DV_BT_CEA_1280X720P24, | 632 | .max_width = 1920, |
643 | V4L2_DV_BT_CEA_1280X720P25, | 633 | .max_height = 1200, |
644 | V4L2_DV_BT_CEA_1280X720P30, | 634 | .min_pixelclock = 25000000, |
645 | V4L2_DV_BT_CEA_1280X720P50, | 635 | .max_pixelclock = 170000000, |
646 | V4L2_DV_BT_CEA_1280X720P60, | 636 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | |
647 | V4L2_DV_BT_CEA_1920X1080P24, | 637 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, |
648 | V4L2_DV_BT_CEA_1920X1080P25, | 638 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | |
649 | V4L2_DV_BT_CEA_1920X1080P30, | 639 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, |
650 | V4L2_DV_BT_CEA_1920X1080P50, | 640 | }, |
651 | V4L2_DV_BT_CEA_1920X1080P60, | ||
652 | |||
653 | V4L2_DV_BT_DMT_640X350P85, | ||
654 | V4L2_DV_BT_DMT_640X400P85, | ||
655 | V4L2_DV_BT_DMT_720X400P85, | ||
656 | V4L2_DV_BT_DMT_640X480P60, | ||
657 | V4L2_DV_BT_DMT_640X480P72, | ||
658 | V4L2_DV_BT_DMT_640X480P75, | ||
659 | V4L2_DV_BT_DMT_640X480P85, | ||
660 | V4L2_DV_BT_DMT_800X600P56, | ||
661 | V4L2_DV_BT_DMT_800X600P60, | ||
662 | V4L2_DV_BT_DMT_800X600P72, | ||
663 | V4L2_DV_BT_DMT_800X600P75, | ||
664 | V4L2_DV_BT_DMT_800X600P85, | ||
665 | V4L2_DV_BT_DMT_848X480P60, | ||
666 | V4L2_DV_BT_DMT_1024X768P60, | ||
667 | V4L2_DV_BT_DMT_1024X768P70, | ||
668 | V4L2_DV_BT_DMT_1024X768P75, | ||
669 | V4L2_DV_BT_DMT_1024X768P85, | ||
670 | V4L2_DV_BT_DMT_1152X864P75, | ||
671 | V4L2_DV_BT_DMT_1280X768P60_RB, | ||
672 | V4L2_DV_BT_DMT_1280X768P60, | ||
673 | V4L2_DV_BT_DMT_1280X768P75, | ||
674 | V4L2_DV_BT_DMT_1280X768P85, | ||
675 | V4L2_DV_BT_DMT_1280X800P60_RB, | ||
676 | V4L2_DV_BT_DMT_1280X800P60, | ||
677 | V4L2_DV_BT_DMT_1280X800P75, | ||
678 | V4L2_DV_BT_DMT_1280X800P85, | ||
679 | V4L2_DV_BT_DMT_1280X960P60, | ||
680 | V4L2_DV_BT_DMT_1280X960P85, | ||
681 | V4L2_DV_BT_DMT_1280X1024P60, | ||
682 | V4L2_DV_BT_DMT_1280X1024P75, | ||
683 | V4L2_DV_BT_DMT_1280X1024P85, | ||
684 | V4L2_DV_BT_DMT_1360X768P60, | ||
685 | V4L2_DV_BT_DMT_1400X1050P60_RB, | ||
686 | V4L2_DV_BT_DMT_1400X1050P60, | ||
687 | V4L2_DV_BT_DMT_1400X1050P75, | ||
688 | V4L2_DV_BT_DMT_1400X1050P85, | ||
689 | V4L2_DV_BT_DMT_1440X900P60_RB, | ||
690 | V4L2_DV_BT_DMT_1440X900P60, | ||
691 | V4L2_DV_BT_DMT_1600X1200P60, | ||
692 | V4L2_DV_BT_DMT_1680X1050P60_RB, | ||
693 | V4L2_DV_BT_DMT_1680X1050P60, | ||
694 | V4L2_DV_BT_DMT_1792X1344P60, | ||
695 | V4L2_DV_BT_DMT_1856X1392P60, | ||
696 | V4L2_DV_BT_DMT_1920X1200P60_RB, | ||
697 | V4L2_DV_BT_DMT_1366X768P60, | ||
698 | V4L2_DV_BT_DMT_1920X1080P60, | ||
699 | {}, | ||
700 | }; | 641 | }; |
701 | 642 | ||
702 | static int ad9389b_s_dv_timings(struct v4l2_subdev *sd, | 643 | static int ad9389b_s_dv_timings(struct v4l2_subdev *sd, |
703 | struct v4l2_dv_timings *timings) | 644 | struct v4l2_dv_timings *timings) |
704 | { | 645 | { |
705 | struct ad9389b_state *state = get_ad9389b_state(sd); | 646 | struct ad9389b_state *state = get_ad9389b_state(sd); |
706 | int i; | ||
707 | 647 | ||
708 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | 648 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); |
709 | 649 | ||
710 | /* quick sanity check */ | 650 | /* quick sanity check */ |
711 | if (timings->type != V4L2_DV_BT_656_1120) | 651 | if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap, NULL, NULL)) |
712 | return -EINVAL; | ||
713 | |||
714 | if (timings->bt.interlaced) | ||
715 | return -EINVAL; | ||
716 | if (timings->bt.pixelclock < 27000000 || | ||
717 | timings->bt.pixelclock > 170000000) | ||
718 | return -EINVAL; | 652 | return -EINVAL; |
719 | 653 | ||
720 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings | 654 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings |
721 | if the format is listed in ad9389b_timings[] */ | 655 | if the format is one of the CEA or DMT timings. */ |
722 | for (i = 0; ad9389b_timings[i].bt.width; i++) { | 656 | v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0, NULL, NULL); |
723 | if (v4l_match_dv_timings(timings, &ad9389b_timings[i], 0)) { | ||
724 | *timings = ad9389b_timings[i]; | ||
725 | break; | ||
726 | } | ||
727 | } | ||
728 | 657 | ||
729 | timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; | 658 | timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; |
730 | 659 | ||
@@ -762,26 +691,14 @@ static int ad9389b_g_dv_timings(struct v4l2_subdev *sd, | |||
762 | static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, | 691 | static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, |
763 | struct v4l2_enum_dv_timings *timings) | 692 | struct v4l2_enum_dv_timings *timings) |
764 | { | 693 | { |
765 | if (timings->index >= ARRAY_SIZE(ad9389b_timings)) | 694 | return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap, |
766 | return -EINVAL; | 695 | NULL, NULL); |
767 | |||
768 | memset(timings->reserved, 0, sizeof(timings->reserved)); | ||
769 | timings->timings = ad9389b_timings[timings->index]; | ||
770 | return 0; | ||
771 | } | 696 | } |
772 | 697 | ||
773 | static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, | 698 | static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, |
774 | struct v4l2_dv_timings_cap *cap) | 699 | struct v4l2_dv_timings_cap *cap) |
775 | { | 700 | { |
776 | cap->type = V4L2_DV_BT_656_1120; | 701 | *cap = ad9389b_timings_cap; |
777 | cap->bt.max_width = 1920; | ||
778 | cap->bt.max_height = 1200; | ||
779 | cap->bt.min_pixelclock = 27000000; | ||
780 | cap->bt.max_pixelclock = 170000000; | ||
781 | cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
782 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT; | ||
783 | cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
784 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM; | ||
785 | return 0; | 702 | return 0; |
786 | } | 703 | } |
787 | 704 | ||
@@ -930,8 +847,10 @@ static void ad9389b_edid_handler(struct work_struct *work) | |||
930 | * (DVI connectors are particularly prone to this problem). */ | 847 | * (DVI connectors are particularly prone to this problem). */ |
931 | if (state->edid.read_retries) { | 848 | if (state->edid.read_retries) { |
932 | state->edid.read_retries--; | 849 | state->edid.read_retries--; |
933 | /* EDID read failed, trigger a retry */ | 850 | v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__); |
934 | ad9389b_wr(sd, 0xc9, 0xf); | 851 | state->have_monitor = false; |
852 | ad9389b_s_power(sd, false); | ||
853 | ad9389b_s_power(sd, true); | ||
935 | queue_delayed_work(state->work_queue, | 854 | queue_delayed_work(state->work_queue, |
936 | &state->edid_handler, EDID_DELAY); | 855 | &state->edid_handler, EDID_DELAY); |
937 | return; | 856 | return; |
@@ -967,11 +886,9 @@ static void ad9389b_setup(struct v4l2_subdev *sd) | |||
967 | ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0); | 886 | ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0); |
968 | /* Output format: RGB 4:4:4 */ | 887 | /* Output format: RGB 4:4:4 */ |
969 | ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0); | 888 | ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0); |
970 | /* CSC fixed point: +/-2, 1st order interpolation 4:2:2 -> 4:4:4 up | 889 | /* 1st order interpolation 4:2:2 -> 4:4:4 up conversion, |
971 | conversion, Aspect ratio: 16:9 */ | 890 | Aspect ratio: 16:9 */ |
972 | ad9389b_wr_and_or(sd, 0x17, 0xe1, 0x0e); | 891 | ad9389b_wr_and_or(sd, 0x17, 0xf9, 0x06); |
973 | /* Disable pixel repetition and CSC */ | ||
974 | ad9389b_wr_and_or(sd, 0x3b, 0x9e, 0x0); | ||
975 | /* Output format: RGB 4:4:4, Active Format Information is valid. */ | 892 | /* Output format: RGB 4:4:4, Active Format Information is valid. */ |
976 | ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08); | 893 | ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08); |
977 | /* Underscanned */ | 894 | /* Underscanned */ |
@@ -1056,12 +973,12 @@ static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd) | |||
1056 | 973 | ||
1057 | static bool edid_block_verify_crc(u8 *edid_block) | 974 | static bool edid_block_verify_crc(u8 *edid_block) |
1058 | { | 975 | { |
1059 | int i; | ||
1060 | u8 sum = 0; | 976 | u8 sum = 0; |
977 | int i; | ||
1061 | 978 | ||
1062 | for (i = 0; i < 127; i++) | 979 | for (i = 0; i < 128; i++) |
1063 | sum += *(edid_block + i); | 980 | sum += edid_block[i]; |
1064 | return ((255 - sum + 1) == edid_block[127]); | 981 | return sum == 0; |
1065 | } | 982 | } |
1066 | 983 | ||
1067 | static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) | 984 | static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) |
@@ -1107,6 +1024,8 @@ static bool ad9389b_check_edid_status(struct v4l2_subdev *sd) | |||
1107 | } | 1024 | } |
1108 | if (!edid_segment_verify_crc(sd, segment)) { | 1025 | if (!edid_segment_verify_crc(sd, segment)) { |
1109 | /* edid crc error, force reread of edid segment */ | 1026 | /* edid crc error, force reread of edid segment */ |
1027 | v4l2_err(sd, "%s: edid crc error\n", __func__); | ||
1028 | state->have_monitor = false; | ||
1110 | ad9389b_s_power(sd, false); | 1029 | ad9389b_s_power(sd, false); |
1111 | ad9389b_s_power(sd, true); | 1030 | ad9389b_s_power(sd, true); |
1112 | return false; | 1031 | return false; |
@@ -1190,27 +1109,27 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * | |||
1190 | state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, | 1109 | state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, |
1191 | V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, | 1110 | V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, |
1192 | 0, V4L2_DV_TX_MODE_DVI_D); | 1111 | 0, V4L2_DV_TX_MODE_DVI_D); |
1193 | state->hdmi_mode_ctrl->is_private = true; | ||
1194 | state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 1112 | state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
1195 | V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0); | 1113 | V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0); |
1196 | state->hotplug_ctrl->is_private = true; | ||
1197 | state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 1114 | state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
1198 | V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0); | 1115 | V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0); |
1199 | state->rx_sense_ctrl->is_private = true; | ||
1200 | state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 1116 | state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
1201 | V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0); | 1117 | V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0); |
1202 | state->have_edid0_ctrl->is_private = true; | ||
1203 | state->rgb_quantization_range_ctrl = | 1118 | state->rgb_quantization_range_ctrl = |
1204 | v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, | 1119 | v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, |
1205 | V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | 1120 | V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, |
1206 | 0, V4L2_DV_RGB_RANGE_AUTO); | 1121 | 0, V4L2_DV_RGB_RANGE_AUTO); |
1207 | state->rgb_quantization_range_ctrl->is_private = true; | ||
1208 | sd->ctrl_handler = hdl; | 1122 | sd->ctrl_handler = hdl; |
1209 | if (hdl->error) { | 1123 | if (hdl->error) { |
1210 | err = hdl->error; | 1124 | err = hdl->error; |
1211 | 1125 | ||
1212 | goto err_hdl; | 1126 | goto err_hdl; |
1213 | } | 1127 | } |
1128 | state->hdmi_mode_ctrl->is_private = true; | ||
1129 | state->hotplug_ctrl->is_private = true; | ||
1130 | state->rx_sense_ctrl->is_private = true; | ||
1131 | state->have_edid0_ctrl->is_private = true; | ||
1132 | state->rgb_quantization_range_ctrl->is_private = true; | ||
1214 | 1133 | ||
1215 | state->pad.flags = MEDIA_PAD_FL_SINK; | 1134 | state->pad.flags = MEDIA_PAD_FL_SINK; |
1216 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | 1135 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); |
diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index 7606218ec4a7..aeb56c53e39f 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c | |||
@@ -27,8 +27,10 @@ | |||
27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
28 | 28 | ||
29 | #include <media/adv7343.h> | 29 | #include <media/adv7343.h> |
30 | #include <media/v4l2-async.h> | ||
30 | #include <media/v4l2-device.h> | 31 | #include <media/v4l2-device.h> |
31 | #include <media/v4l2-ctrls.h> | 32 | #include <media/v4l2-ctrls.h> |
33 | #include <media/v4l2-of.h> | ||
32 | 34 | ||
33 | #include "adv7343_regs.h" | 35 | #include "adv7343_regs.h" |
34 | 36 | ||
@@ -226,12 +228,12 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type) | |||
226 | else | 228 | else |
227 | val = state->pdata->mode_config.sleep_mode << 0 | | 229 | val = state->pdata->mode_config.sleep_mode << 0 | |
228 | state->pdata->mode_config.pll_control << 1 | | 230 | state->pdata->mode_config.pll_control << 1 | |
229 | state->pdata->mode_config.dac_3 << 2 | | 231 | state->pdata->mode_config.dac[2] << 2 | |
230 | state->pdata->mode_config.dac_2 << 3 | | 232 | state->pdata->mode_config.dac[1] << 3 | |
231 | state->pdata->mode_config.dac_1 << 4 | | 233 | state->pdata->mode_config.dac[0] << 4 | |
232 | state->pdata->mode_config.dac_6 << 5 | | 234 | state->pdata->mode_config.dac[5] << 5 | |
233 | state->pdata->mode_config.dac_5 << 6 | | 235 | state->pdata->mode_config.dac[4] << 6 | |
234 | state->pdata->mode_config.dac_4 << 7; | 236 | state->pdata->mode_config.dac[3] << 7; |
235 | 237 | ||
236 | err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val); | 238 | err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val); |
237 | if (err < 0) | 239 | if (err < 0) |
@@ -250,15 +252,15 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type) | |||
250 | /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */ | 252 | /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */ |
251 | val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI); | 253 | val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI); |
252 | 254 | ||
253 | if (state->pdata && state->pdata->sd_config.sd_dac_out1) | 255 | if (state->pdata && state->pdata->sd_config.sd_dac_out[0]) |
254 | val = val | (state->pdata->sd_config.sd_dac_out1 << 1); | 256 | val = val | (state->pdata->sd_config.sd_dac_out[0] << 1); |
255 | else if (state->pdata && !state->pdata->sd_config.sd_dac_out1) | 257 | else if (state->pdata && !state->pdata->sd_config.sd_dac_out[0]) |
256 | val = val & ~(state->pdata->sd_config.sd_dac_out1 << 1); | 258 | val = val & ~(state->pdata->sd_config.sd_dac_out[0] << 1); |
257 | 259 | ||
258 | if (state->pdata && state->pdata->sd_config.sd_dac_out2) | 260 | if (state->pdata && state->pdata->sd_config.sd_dac_out[1]) |
259 | val = val | (state->pdata->sd_config.sd_dac_out2 << 2); | 261 | val = val | (state->pdata->sd_config.sd_dac_out[1] << 2); |
260 | else if (state->pdata && !state->pdata->sd_config.sd_dac_out2) | 262 | else if (state->pdata && !state->pdata->sd_config.sd_dac_out[1]) |
261 | val = val & ~(state->pdata->sd_config.sd_dac_out2 << 2); | 263 | val = val & ~(state->pdata->sd_config.sd_dac_out[1] << 2); |
262 | 264 | ||
263 | err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val); | 265 | err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val); |
264 | if (err < 0) | 266 | if (err < 0) |
@@ -398,6 +400,40 @@ static int adv7343_initialize(struct v4l2_subdev *sd) | |||
398 | return err; | 400 | return err; |
399 | } | 401 | } |
400 | 402 | ||
403 | static struct adv7343_platform_data * | ||
404 | adv7343_get_pdata(struct i2c_client *client) | ||
405 | { | ||
406 | struct adv7343_platform_data *pdata; | ||
407 | struct device_node *np; | ||
408 | |||
409 | if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) | ||
410 | return client->dev.platform_data; | ||
411 | |||
412 | np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); | ||
413 | if (!np) | ||
414 | return NULL; | ||
415 | |||
416 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); | ||
417 | if (!pdata) | ||
418 | goto done; | ||
419 | |||
420 | pdata->mode_config.sleep_mode = | ||
421 | of_property_read_bool(np, "adi,power-mode-sleep-mode"); | ||
422 | |||
423 | pdata->mode_config.pll_control = | ||
424 | of_property_read_bool(np, "adi,power-mode-pll-ctrl"); | ||
425 | |||
426 | of_property_read_u32_array(np, "adi,dac-enable", | ||
427 | pdata->mode_config.dac, 6); | ||
428 | |||
429 | of_property_read_u32_array(np, "adi,sd-dac-enable", | ||
430 | pdata->sd_config.sd_dac_out, 2); | ||
431 | |||
432 | done: | ||
433 | of_node_put(np); | ||
434 | return pdata; | ||
435 | } | ||
436 | |||
401 | static int adv7343_probe(struct i2c_client *client, | 437 | static int adv7343_probe(struct i2c_client *client, |
402 | const struct i2c_device_id *id) | 438 | const struct i2c_device_id *id) |
403 | { | 439 | { |
@@ -416,7 +452,7 @@ static int adv7343_probe(struct i2c_client *client, | |||
416 | return -ENOMEM; | 452 | return -ENOMEM; |
417 | 453 | ||
418 | /* Copy board specific information here */ | 454 | /* Copy board specific information here */ |
419 | state->pdata = client->dev.platform_data; | 455 | state->pdata = adv7343_get_pdata(client); |
420 | 456 | ||
421 | state->reg00 = 0x80; | 457 | state->reg00 = 0x80; |
422 | state->reg01 = 0x00; | 458 | state->reg01 = 0x00; |
@@ -445,16 +481,21 @@ static int adv7343_probe(struct i2c_client *client, | |||
445 | ADV7343_GAIN_DEF); | 481 | ADV7343_GAIN_DEF); |
446 | state->sd.ctrl_handler = &state->hdl; | 482 | state->sd.ctrl_handler = &state->hdl; |
447 | if (state->hdl.error) { | 483 | if (state->hdl.error) { |
448 | int err = state->hdl.error; | 484 | err = state->hdl.error; |
449 | 485 | goto done; | |
450 | v4l2_ctrl_handler_free(&state->hdl); | ||
451 | return err; | ||
452 | } | 486 | } |
453 | v4l2_ctrl_handler_setup(&state->hdl); | 487 | v4l2_ctrl_handler_setup(&state->hdl); |
454 | 488 | ||
455 | err = adv7343_initialize(&state->sd); | 489 | err = adv7343_initialize(&state->sd); |
456 | if (err) | 490 | if (err) |
491 | goto done; | ||
492 | |||
493 | err = v4l2_async_register_subdev(&state->sd); | ||
494 | |||
495 | done: | ||
496 | if (err < 0) | ||
457 | v4l2_ctrl_handler_free(&state->hdl); | 497 | v4l2_ctrl_handler_free(&state->hdl); |
498 | |||
458 | return err; | 499 | return err; |
459 | } | 500 | } |
460 | 501 | ||
@@ -463,6 +504,7 @@ static int adv7343_remove(struct i2c_client *client) | |||
463 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 504 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
464 | struct adv7343_state *state = to_state(sd); | 505 | struct adv7343_state *state = to_state(sd); |
465 | 506 | ||
507 | v4l2_async_unregister_subdev(&state->sd); | ||
466 | v4l2_device_unregister_subdev(sd); | 508 | v4l2_device_unregister_subdev(sd); |
467 | v4l2_ctrl_handler_free(&state->hdl); | 509 | v4l2_ctrl_handler_free(&state->hdl); |
468 | 510 | ||
@@ -476,8 +518,17 @@ static const struct i2c_device_id adv7343_id[] = { | |||
476 | 518 | ||
477 | MODULE_DEVICE_TABLE(i2c, adv7343_id); | 519 | MODULE_DEVICE_TABLE(i2c, adv7343_id); |
478 | 520 | ||
521 | #if IS_ENABLED(CONFIG_OF) | ||
522 | static const struct of_device_id adv7343_of_match[] = { | ||
523 | {.compatible = "adi,adv7343", }, | ||
524 | { /* sentinel */ }, | ||
525 | }; | ||
526 | MODULE_DEVICE_TABLE(of, adv7343_of_match); | ||
527 | #endif | ||
528 | |||
479 | static struct i2c_driver adv7343_driver = { | 529 | static struct i2c_driver adv7343_driver = { |
480 | .driver = { | 530 | .driver = { |
531 | .of_match_table = of_match_ptr(adv7343_of_match), | ||
481 | .owner = THIS_MODULE, | 532 | .owner = THIS_MODULE, |
482 | .name = "adv7343", | 533 | .name = "adv7343", |
483 | }, | 534 | }, |
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c new file mode 100644 index 000000000000..7a576097471f --- /dev/null +++ b/drivers/media/i2c/adv7511.c | |||
@@ -0,0 +1,1198 @@ | |||
1 | /* | ||
2 | * Analog Devices ADV7511 HDMI Transmitter Device Driver | ||
3 | * | ||
4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you may redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
17 | * SOFTWARE. | ||
18 | */ | ||
19 | |||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/videodev2.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/workqueue.h> | ||
29 | #include <linux/v4l2-dv-timings.h> | ||
30 | #include <media/v4l2-device.h> | ||
31 | #include <media/v4l2-common.h> | ||
32 | #include <media/v4l2-ctrls.h> | ||
33 | #include <media/v4l2-dv-timings.h> | ||
34 | #include <media/adv7511.h> | ||
35 | |||
36 | static int debug; | ||
37 | module_param(debug, int, 0644); | ||
38 | MODULE_PARM_DESC(debug, "debug level (0-2)"); | ||
39 | |||
40 | MODULE_DESCRIPTION("Analog Devices ADV7511 HDMI Transmitter Device Driver"); | ||
41 | MODULE_AUTHOR("Hans Verkuil"); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | |||
44 | #define MASK_ADV7511_EDID_RDY_INT 0x04 | ||
45 | #define MASK_ADV7511_MSEN_INT 0x40 | ||
46 | #define MASK_ADV7511_HPD_INT 0x80 | ||
47 | |||
48 | #define MASK_ADV7511_HPD_DETECT 0x40 | ||
49 | #define MASK_ADV7511_MSEN_DETECT 0x20 | ||
50 | #define MASK_ADV7511_EDID_RDY 0x10 | ||
51 | |||
52 | #define EDID_MAX_RETRIES (8) | ||
53 | #define EDID_DELAY 250 | ||
54 | #define EDID_MAX_SEGM 8 | ||
55 | |||
56 | #define ADV7511_MAX_WIDTH 1920 | ||
57 | #define ADV7511_MAX_HEIGHT 1200 | ||
58 | #define ADV7511_MIN_PIXELCLOCK 20000000 | ||
59 | #define ADV7511_MAX_PIXELCLOCK 225000000 | ||
60 | |||
61 | /* | ||
62 | ********************************************************************** | ||
63 | * | ||
64 | * Arrays with configuration parameters for the ADV7511 | ||
65 | * | ||
66 | ********************************************************************** | ||
67 | */ | ||
68 | |||
69 | struct i2c_reg_value { | ||
70 | unsigned char reg; | ||
71 | unsigned char value; | ||
72 | }; | ||
73 | |||
74 | struct adv7511_state_edid { | ||
75 | /* total number of blocks */ | ||
76 | u32 blocks; | ||
77 | /* Number of segments read */ | ||
78 | u32 segments; | ||
79 | uint8_t data[EDID_MAX_SEGM * 256]; | ||
80 | /* Number of EDID read retries left */ | ||
81 | unsigned read_retries; | ||
82 | bool complete; | ||
83 | }; | ||
84 | |||
85 | struct adv7511_state { | ||
86 | struct adv7511_platform_data pdata; | ||
87 | struct v4l2_subdev sd; | ||
88 | struct media_pad pad; | ||
89 | struct v4l2_ctrl_handler hdl; | ||
90 | int chip_revision; | ||
91 | uint8_t i2c_edid_addr; | ||
92 | uint8_t i2c_cec_addr; | ||
93 | /* Is the adv7511 powered on? */ | ||
94 | bool power_on; | ||
95 | /* Did we receive hotplug and rx-sense signals? */ | ||
96 | bool have_monitor; | ||
97 | /* timings from s_dv_timings */ | ||
98 | struct v4l2_dv_timings dv_timings; | ||
99 | /* controls */ | ||
100 | struct v4l2_ctrl *hdmi_mode_ctrl; | ||
101 | struct v4l2_ctrl *hotplug_ctrl; | ||
102 | struct v4l2_ctrl *rx_sense_ctrl; | ||
103 | struct v4l2_ctrl *have_edid0_ctrl; | ||
104 | struct v4l2_ctrl *rgb_quantization_range_ctrl; | ||
105 | struct i2c_client *i2c_edid; | ||
106 | struct adv7511_state_edid edid; | ||
107 | /* Running counter of the number of detected EDIDs (for debugging) */ | ||
108 | unsigned edid_detect_counter; | ||
109 | struct workqueue_struct *work_queue; | ||
110 | struct delayed_work edid_handler; /* work entry */ | ||
111 | }; | ||
112 | |||
113 | static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd); | ||
114 | static bool adv7511_check_edid_status(struct v4l2_subdev *sd); | ||
115 | static void adv7511_setup(struct v4l2_subdev *sd); | ||
116 | static int adv7511_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq); | ||
117 | static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq); | ||
118 | |||
119 | |||
120 | static const struct v4l2_dv_timings_cap adv7511_timings_cap = { | ||
121 | .type = V4L2_DV_BT_656_1120, | ||
122 | .bt = { | ||
123 | .max_width = ADV7511_MAX_WIDTH, | ||
124 | .max_height = ADV7511_MAX_HEIGHT, | ||
125 | .min_pixelclock = ADV7511_MIN_PIXELCLOCK, | ||
126 | .max_pixelclock = ADV7511_MAX_PIXELCLOCK, | ||
127 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
128 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, | ||
129 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
130 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, | ||
131 | }, | ||
132 | }; | ||
133 | |||
134 | static inline struct adv7511_state *get_adv7511_state(struct v4l2_subdev *sd) | ||
135 | { | ||
136 | return container_of(sd, struct adv7511_state, sd); | ||
137 | } | ||
138 | |||
139 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | ||
140 | { | ||
141 | return &container_of(ctrl->handler, struct adv7511_state, hdl)->sd; | ||
142 | } | ||
143 | |||
144 | /* ------------------------ I2C ----------------------------------------------- */ | ||
145 | |||
146 | static s32 adv_smbus_read_byte_data_check(struct i2c_client *client, | ||
147 | u8 command, bool check) | ||
148 | { | ||
149 | union i2c_smbus_data data; | ||
150 | |||
151 | if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
152 | I2C_SMBUS_READ, command, | ||
153 | I2C_SMBUS_BYTE_DATA, &data)) | ||
154 | return data.byte; | ||
155 | if (check) | ||
156 | v4l_err(client, "error reading %02x, %02x\n", | ||
157 | client->addr, command); | ||
158 | return -1; | ||
159 | } | ||
160 | |||
161 | static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command) | ||
162 | { | ||
163 | int i; | ||
164 | for (i = 0; i < 3; i++) { | ||
165 | int ret = adv_smbus_read_byte_data_check(client, command, true); | ||
166 | if (ret >= 0) { | ||
167 | if (i) | ||
168 | v4l_err(client, "read ok after %d retries\n", i); | ||
169 | return ret; | ||
170 | } | ||
171 | } | ||
172 | v4l_err(client, "read failed\n"); | ||
173 | return -1; | ||
174 | } | ||
175 | |||
176 | static int adv7511_rd(struct v4l2_subdev *sd, u8 reg) | ||
177 | { | ||
178 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
179 | |||
180 | return adv_smbus_read_byte_data(client, reg); | ||
181 | } | ||
182 | |||
183 | static int adv7511_wr(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
184 | { | ||
185 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
186 | int ret; | ||
187 | int i; | ||
188 | |||
189 | for (i = 0; i < 3; i++) { | ||
190 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
191 | if (ret == 0) | ||
192 | return 0; | ||
193 | } | ||
194 | v4l2_err(sd, "%s: i2c write error\n", __func__); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | /* To set specific bits in the register, a clear-mask is given (to be AND-ed), | ||
199 | and then the value-mask (to be OR-ed). */ | ||
200 | static inline void adv7511_wr_and_or(struct v4l2_subdev *sd, u8 reg, uint8_t clr_mask, uint8_t val_mask) | ||
201 | { | ||
202 | adv7511_wr(sd, reg, (adv7511_rd(sd, reg) & clr_mask) | val_mask); | ||
203 | } | ||
204 | |||
205 | static int adv_smbus_read_i2c_block_data(struct i2c_client *client, | ||
206 | u8 command, unsigned length, u8 *values) | ||
207 | { | ||
208 | union i2c_smbus_data data; | ||
209 | int ret; | ||
210 | |||
211 | if (length > I2C_SMBUS_BLOCK_MAX) | ||
212 | length = I2C_SMBUS_BLOCK_MAX; | ||
213 | data.block[0] = length; | ||
214 | |||
215 | ret = i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
216 | I2C_SMBUS_READ, command, | ||
217 | I2C_SMBUS_I2C_BLOCK_DATA, &data); | ||
218 | memcpy(values, data.block + 1, length); | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static inline void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t *buf) | ||
223 | { | ||
224 | struct adv7511_state *state = get_adv7511_state(sd); | ||
225 | int i; | ||
226 | int err = 0; | ||
227 | |||
228 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
229 | |||
230 | for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX) | ||
231 | err = adv_smbus_read_i2c_block_data(state->i2c_edid, i, | ||
232 | I2C_SMBUS_BLOCK_MAX, buf + i); | ||
233 | if (err) | ||
234 | v4l2_err(sd, "%s: i2c read error\n", __func__); | ||
235 | } | ||
236 | |||
237 | static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd) | ||
238 | { | ||
239 | return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT; | ||
240 | } | ||
241 | |||
242 | static inline bool adv7511_have_rx_sense(struct v4l2_subdev *sd) | ||
243 | { | ||
244 | return adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT; | ||
245 | } | ||
246 | |||
247 | static void adv7511_csc_conversion_mode(struct v4l2_subdev *sd, uint8_t mode) | ||
248 | { | ||
249 | adv7511_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5); | ||
250 | } | ||
251 | |||
252 | static void adv7511_csc_coeff(struct v4l2_subdev *sd, | ||
253 | u16 A1, u16 A2, u16 A3, u16 A4, | ||
254 | u16 B1, u16 B2, u16 B3, u16 B4, | ||
255 | u16 C1, u16 C2, u16 C3, u16 C4) | ||
256 | { | ||
257 | /* A */ | ||
258 | adv7511_wr_and_or(sd, 0x18, 0xe0, A1>>8); | ||
259 | adv7511_wr(sd, 0x19, A1); | ||
260 | adv7511_wr_and_or(sd, 0x1A, 0xe0, A2>>8); | ||
261 | adv7511_wr(sd, 0x1B, A2); | ||
262 | adv7511_wr_and_or(sd, 0x1c, 0xe0, A3>>8); | ||
263 | adv7511_wr(sd, 0x1d, A3); | ||
264 | adv7511_wr_and_or(sd, 0x1e, 0xe0, A4>>8); | ||
265 | adv7511_wr(sd, 0x1f, A4); | ||
266 | |||
267 | /* B */ | ||
268 | adv7511_wr_and_or(sd, 0x20, 0xe0, B1>>8); | ||
269 | adv7511_wr(sd, 0x21, B1); | ||
270 | adv7511_wr_and_or(sd, 0x22, 0xe0, B2>>8); | ||
271 | adv7511_wr(sd, 0x23, B2); | ||
272 | adv7511_wr_and_or(sd, 0x24, 0xe0, B3>>8); | ||
273 | adv7511_wr(sd, 0x25, B3); | ||
274 | adv7511_wr_and_or(sd, 0x26, 0xe0, B4>>8); | ||
275 | adv7511_wr(sd, 0x27, B4); | ||
276 | |||
277 | /* C */ | ||
278 | adv7511_wr_and_or(sd, 0x28, 0xe0, C1>>8); | ||
279 | adv7511_wr(sd, 0x29, C1); | ||
280 | adv7511_wr_and_or(sd, 0x2A, 0xe0, C2>>8); | ||
281 | adv7511_wr(sd, 0x2B, C2); | ||
282 | adv7511_wr_and_or(sd, 0x2C, 0xe0, C3>>8); | ||
283 | adv7511_wr(sd, 0x2D, C3); | ||
284 | adv7511_wr_and_or(sd, 0x2E, 0xe0, C4>>8); | ||
285 | adv7511_wr(sd, 0x2F, C4); | ||
286 | } | ||
287 | |||
288 | static void adv7511_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable) | ||
289 | { | ||
290 | if (enable) { | ||
291 | uint8_t csc_mode = 0; | ||
292 | adv7511_csc_conversion_mode(sd, csc_mode); | ||
293 | adv7511_csc_coeff(sd, | ||
294 | 4096-564, 0, 0, 256, | ||
295 | 0, 4096-564, 0, 256, | ||
296 | 0, 0, 4096-564, 256); | ||
297 | /* enable CSC */ | ||
298 | adv7511_wr_and_or(sd, 0x18, 0x7f, 0x80); | ||
299 | /* AVI infoframe: Limited range RGB (16-235) */ | ||
300 | adv7511_wr_and_or(sd, 0x57, 0xf3, 0x04); | ||
301 | } else { | ||
302 | /* disable CSC */ | ||
303 | adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0); | ||
304 | /* AVI infoframe: Full range RGB (0-255) */ | ||
305 | adv7511_wr_and_or(sd, 0x57, 0xf3, 0x08); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | static void adv7511_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd) | ||
310 | { | ||
311 | struct adv7511_state *state = get_adv7511_state(sd); | ||
312 | if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) { | ||
313 | /* CEA format, not IT */ | ||
314 | adv7511_wr_and_or(sd, 0x57, 0x7f, 0x00); | ||
315 | } else { | ||
316 | /* IT format */ | ||
317 | adv7511_wr_and_or(sd, 0x57, 0x7f, 0x80); | ||
318 | } | ||
319 | } | ||
320 | |||
321 | static int adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl) | ||
322 | { | ||
323 | switch (ctrl->val) { | ||
324 | default: | ||
325 | return -EINVAL; | ||
326 | break; | ||
327 | case V4L2_DV_RGB_RANGE_AUTO: { | ||
328 | /* automatic */ | ||
329 | struct adv7511_state *state = get_adv7511_state(sd); | ||
330 | |||
331 | if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) { | ||
332 | /* cea format, RGB limited range (16-235) */ | ||
333 | adv7511_csc_rgb_full2limit(sd, true); | ||
334 | } else { | ||
335 | /* not cea format, RGB full range (0-255) */ | ||
336 | adv7511_csc_rgb_full2limit(sd, false); | ||
337 | } | ||
338 | } | ||
339 | break; | ||
340 | case V4L2_DV_RGB_RANGE_LIMITED: | ||
341 | /* RGB limited range (16-235) */ | ||
342 | adv7511_csc_rgb_full2limit(sd, true); | ||
343 | break; | ||
344 | case V4L2_DV_RGB_RANGE_FULL: | ||
345 | /* RGB full range (0-255) */ | ||
346 | adv7511_csc_rgb_full2limit(sd, false); | ||
347 | break; | ||
348 | } | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | /* ------------------------------ CTRL OPS ------------------------------ */ | ||
353 | |||
354 | static int adv7511_s_ctrl(struct v4l2_ctrl *ctrl) | ||
355 | { | ||
356 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
357 | struct adv7511_state *state = get_adv7511_state(sd); | ||
358 | |||
359 | v4l2_dbg(1, debug, sd, "%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val); | ||
360 | |||
361 | if (state->hdmi_mode_ctrl == ctrl) { | ||
362 | /* Set HDMI or DVI-D */ | ||
363 | adv7511_wr_and_or(sd, 0xaf, 0xfd, ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00); | ||
364 | return 0; | ||
365 | } | ||
366 | if (state->rgb_quantization_range_ctrl == ctrl) | ||
367 | return adv7511_set_rgb_quantization_mode(sd, ctrl); | ||
368 | |||
369 | return -EINVAL; | ||
370 | } | ||
371 | |||
372 | static const struct v4l2_ctrl_ops adv7511_ctrl_ops = { | ||
373 | .s_ctrl = adv7511_s_ctrl, | ||
374 | }; | ||
375 | |||
376 | /* ---------------------------- CORE OPS ------------------------------------------- */ | ||
377 | |||
378 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
379 | static void adv7511_inv_register(struct v4l2_subdev *sd) | ||
380 | { | ||
381 | v4l2_info(sd, "0x000-0x0ff: Main Map\n"); | ||
382 | } | ||
383 | |||
384 | static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) | ||
385 | { | ||
386 | reg->size = 1; | ||
387 | switch (reg->reg >> 8) { | ||
388 | case 0: | ||
389 | reg->val = adv7511_rd(sd, reg->reg & 0xff); | ||
390 | break; | ||
391 | default: | ||
392 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | ||
393 | adv7511_inv_register(sd); | ||
394 | break; | ||
395 | } | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) | ||
400 | { | ||
401 | switch (reg->reg >> 8) { | ||
402 | case 0: | ||
403 | adv7511_wr(sd, reg->reg & 0xff, reg->val & 0xff); | ||
404 | break; | ||
405 | default: | ||
406 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | ||
407 | adv7511_inv_register(sd); | ||
408 | break; | ||
409 | } | ||
410 | return 0; | ||
411 | } | ||
412 | #endif | ||
413 | |||
414 | static int adv7511_log_status(struct v4l2_subdev *sd) | ||
415 | { | ||
416 | struct adv7511_state *state = get_adv7511_state(sd); | ||
417 | struct adv7511_state_edid *edid = &state->edid; | ||
418 | |||
419 | static const char * const states[] = { | ||
420 | "in reset", | ||
421 | "reading EDID", | ||
422 | "idle", | ||
423 | "initializing HDCP", | ||
424 | "HDCP enabled", | ||
425 | "initializing HDCP repeater", | ||
426 | "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" | ||
427 | }; | ||
428 | static const char * const errors[] = { | ||
429 | "no error", | ||
430 | "bad receiver BKSV", | ||
431 | "Ri mismatch", | ||
432 | "Pj mismatch", | ||
433 | "i2c error", | ||
434 | "timed out", | ||
435 | "max repeater cascade exceeded", | ||
436 | "hash check failed", | ||
437 | "too many devices", | ||
438 | "9", "A", "B", "C", "D", "E", "F" | ||
439 | }; | ||
440 | |||
441 | v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off"); | ||
442 | v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n", | ||
443 | (adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT) ? "detected" : "no", | ||
444 | (adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT) ? "detected" : "no", | ||
445 | edid->segments ? "found" : "no", | ||
446 | edid->blocks); | ||
447 | v4l2_info(sd, "%s output %s\n", | ||
448 | (adv7511_rd(sd, 0xaf) & 0x02) ? | ||
449 | "HDMI" : "DVI-D", | ||
450 | (adv7511_rd(sd, 0xa1) & 0x3c) ? | ||
451 | "disabled" : "enabled"); | ||
452 | v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n", | ||
453 | states[adv7511_rd(sd, 0xc8) & 0xf], | ||
454 | errors[adv7511_rd(sd, 0xc8) >> 4], state->edid_detect_counter, | ||
455 | adv7511_rd(sd, 0x94), adv7511_rd(sd, 0x96)); | ||
456 | v4l2_info(sd, "RGB quantization: %s range\n", adv7511_rd(sd, 0x18) & 0x80 ? "limited" : "full"); | ||
457 | if (state->dv_timings.type == V4L2_DV_BT_656_1120) | ||
458 | v4l2_print_dv_timings(sd->name, "timings: ", | ||
459 | &state->dv_timings, false); | ||
460 | else | ||
461 | v4l2_info(sd, "no timings set\n"); | ||
462 | v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr); | ||
463 | v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | /* Power up/down adv7511 */ | ||
468 | static int adv7511_s_power(struct v4l2_subdev *sd, int on) | ||
469 | { | ||
470 | struct adv7511_state *state = get_adv7511_state(sd); | ||
471 | const int retries = 20; | ||
472 | int i; | ||
473 | |||
474 | v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off"); | ||
475 | |||
476 | state->power_on = on; | ||
477 | |||
478 | if (!on) { | ||
479 | /* Power down */ | ||
480 | adv7511_wr_and_or(sd, 0x41, 0xbf, 0x40); | ||
481 | return true; | ||
482 | } | ||
483 | |||
484 | /* Power up */ | ||
485 | /* The adv7511 does not always come up immediately. | ||
486 | Retry multiple times. */ | ||
487 | for (i = 0; i < retries; i++) { | ||
488 | adv7511_wr_and_or(sd, 0x41, 0xbf, 0x0); | ||
489 | if ((adv7511_rd(sd, 0x41) & 0x40) == 0) | ||
490 | break; | ||
491 | adv7511_wr_and_or(sd, 0x41, 0xbf, 0x40); | ||
492 | msleep(10); | ||
493 | } | ||
494 | if (i == retries) { | ||
495 | v4l2_dbg(1, debug, sd, "%s: failed to powerup the adv7511!\n", __func__); | ||
496 | adv7511_s_power(sd, 0); | ||
497 | return false; | ||
498 | } | ||
499 | if (i > 1) | ||
500 | v4l2_dbg(1, debug, sd, "%s: needed %d retries to powerup the adv7511\n", __func__, i); | ||
501 | |||
502 | /* Reserved registers that must be set */ | ||
503 | adv7511_wr(sd, 0x98, 0x03); | ||
504 | adv7511_wr_and_or(sd, 0x9a, 0xfe, 0x70); | ||
505 | adv7511_wr(sd, 0x9c, 0x30); | ||
506 | adv7511_wr_and_or(sd, 0x9d, 0xfc, 0x01); | ||
507 | adv7511_wr(sd, 0xa2, 0xa4); | ||
508 | adv7511_wr(sd, 0xa3, 0xa4); | ||
509 | adv7511_wr(sd, 0xe0, 0xd0); | ||
510 | adv7511_wr(sd, 0xf9, 0x00); | ||
511 | |||
512 | adv7511_wr(sd, 0x43, state->i2c_edid_addr); | ||
513 | |||
514 | /* Set number of attempts to read the EDID */ | ||
515 | adv7511_wr(sd, 0xc9, 0xf); | ||
516 | return true; | ||
517 | } | ||
518 | |||
519 | /* Enable interrupts */ | ||
520 | static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable) | ||
521 | { | ||
522 | uint8_t irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT; | ||
523 | uint8_t irqs_rd; | ||
524 | int retries = 100; | ||
525 | |||
526 | v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable"); | ||
527 | |||
528 | /* The datasheet says that the EDID ready interrupt should be | ||
529 | disabled if there is no hotplug. */ | ||
530 | if (!enable) | ||
531 | irqs = 0; | ||
532 | else if (adv7511_have_hotplug(sd)) | ||
533 | irqs |= MASK_ADV7511_EDID_RDY_INT; | ||
534 | |||
535 | /* | ||
536 | * This i2c write can fail (approx. 1 in 1000 writes). But it | ||
537 | * is essential that this register is correct, so retry it | ||
538 | * multiple times. | ||
539 | * | ||
540 | * Note that the i2c write does not report an error, but the readback | ||
541 | * clearly shows the wrong value. | ||
542 | */ | ||
543 | do { | ||
544 | adv7511_wr(sd, 0x94, irqs); | ||
545 | irqs_rd = adv7511_rd(sd, 0x94); | ||
546 | } while (retries-- && irqs_rd != irqs); | ||
547 | |||
548 | if (irqs_rd == irqs) | ||
549 | return; | ||
550 | v4l2_err(sd, "Could not set interrupts: hw failure?\n"); | ||
551 | } | ||
552 | |||
553 | /* Interrupt handler */ | ||
554 | static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | ||
555 | { | ||
556 | uint8_t irq_status; | ||
557 | |||
558 | /* disable interrupts to prevent a race condition */ | ||
559 | adv7511_set_isr(sd, false); | ||
560 | irq_status = adv7511_rd(sd, 0x96); | ||
561 | /* clear detected interrupts */ | ||
562 | adv7511_wr(sd, 0x96, irq_status); | ||
563 | |||
564 | v4l2_dbg(1, debug, sd, "%s: irq 0x%x\n", __func__, irq_status); | ||
565 | |||
566 | if (irq_status & (MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT)) | ||
567 | adv7511_check_monitor_present_status(sd); | ||
568 | if (irq_status & MASK_ADV7511_EDID_RDY_INT) | ||
569 | adv7511_check_edid_status(sd); | ||
570 | |||
571 | /* enable interrupts */ | ||
572 | adv7511_set_isr(sd, true); | ||
573 | |||
574 | if (handled) | ||
575 | *handled = true; | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid) | ||
580 | { | ||
581 | struct adv7511_state *state = get_adv7511_state(sd); | ||
582 | |||
583 | if (edid->pad != 0) | ||
584 | return -EINVAL; | ||
585 | if ((edid->blocks == 0) || (edid->blocks > 256)) | ||
586 | return -EINVAL; | ||
587 | if (!edid->edid) | ||
588 | return -EINVAL; | ||
589 | if (!state->edid.segments) { | ||
590 | v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); | ||
591 | return -ENODATA; | ||
592 | } | ||
593 | if (edid->start_block >= state->edid.segments * 2) | ||
594 | return -E2BIG; | ||
595 | if ((edid->blocks + edid->start_block) >= state->edid.segments * 2) | ||
596 | edid->blocks = state->edid.segments * 2 - edid->start_block; | ||
597 | |||
598 | memcpy(edid->edid, &state->edid.data[edid->start_block * 128], | ||
599 | 128 * edid->blocks); | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static const struct v4l2_subdev_pad_ops adv7511_pad_ops = { | ||
604 | .get_edid = adv7511_get_edid, | ||
605 | }; | ||
606 | |||
607 | static const struct v4l2_subdev_core_ops adv7511_core_ops = { | ||
608 | .log_status = adv7511_log_status, | ||
609 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
610 | .g_register = adv7511_g_register, | ||
611 | .s_register = adv7511_s_register, | ||
612 | #endif | ||
613 | .s_power = adv7511_s_power, | ||
614 | .interrupt_service_routine = adv7511_isr, | ||
615 | }; | ||
616 | |||
617 | /* ------------------------------ VIDEO OPS ------------------------------ */ | ||
618 | |||
619 | /* Enable/disable adv7511 output */ | ||
620 | static int adv7511_s_stream(struct v4l2_subdev *sd, int enable) | ||
621 | { | ||
622 | struct adv7511_state *state = get_adv7511_state(sd); | ||
623 | |||
624 | v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); | ||
625 | adv7511_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c)); | ||
626 | if (enable) { | ||
627 | adv7511_check_monitor_present_status(sd); | ||
628 | } else { | ||
629 | adv7511_s_power(sd, 0); | ||
630 | state->have_monitor = false; | ||
631 | } | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | static int adv7511_s_dv_timings(struct v4l2_subdev *sd, | ||
636 | struct v4l2_dv_timings *timings) | ||
637 | { | ||
638 | struct adv7511_state *state = get_adv7511_state(sd); | ||
639 | |||
640 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
641 | |||
642 | /* quick sanity check */ | ||
643 | if (!v4l2_valid_dv_timings(timings, &adv7511_timings_cap, NULL, NULL)) | ||
644 | return -EINVAL; | ||
645 | |||
646 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings | ||
647 | if the format is one of the CEA or DMT timings. */ | ||
648 | v4l2_find_dv_timings_cap(timings, &adv7511_timings_cap, 0, NULL, NULL); | ||
649 | |||
650 | timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; | ||
651 | |||
652 | /* save timings */ | ||
653 | state->dv_timings = *timings; | ||
654 | |||
655 | /* update quantization range based on new dv_timings */ | ||
656 | adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl); | ||
657 | |||
658 | /* update AVI infoframe */ | ||
659 | adv7511_set_IT_content_AVI_InfoFrame(sd); | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static int adv7511_g_dv_timings(struct v4l2_subdev *sd, | ||
665 | struct v4l2_dv_timings *timings) | ||
666 | { | ||
667 | struct adv7511_state *state = get_adv7511_state(sd); | ||
668 | |||
669 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
670 | |||
671 | if (!timings) | ||
672 | return -EINVAL; | ||
673 | |||
674 | *timings = state->dv_timings; | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int adv7511_enum_dv_timings(struct v4l2_subdev *sd, | ||
680 | struct v4l2_enum_dv_timings *timings) | ||
681 | { | ||
682 | return v4l2_enum_dv_timings_cap(timings, &adv7511_timings_cap, NULL, NULL); | ||
683 | } | ||
684 | |||
685 | static int adv7511_dv_timings_cap(struct v4l2_subdev *sd, | ||
686 | struct v4l2_dv_timings_cap *cap) | ||
687 | { | ||
688 | *cap = adv7511_timings_cap; | ||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | static const struct v4l2_subdev_video_ops adv7511_video_ops = { | ||
693 | .s_stream = adv7511_s_stream, | ||
694 | .s_dv_timings = adv7511_s_dv_timings, | ||
695 | .g_dv_timings = adv7511_g_dv_timings, | ||
696 | .enum_dv_timings = adv7511_enum_dv_timings, | ||
697 | .dv_timings_cap = adv7511_dv_timings_cap, | ||
698 | }; | ||
699 | |||
700 | /* ------------------------------ AUDIO OPS ------------------------------ */ | ||
701 | static int adv7511_s_audio_stream(struct v4l2_subdev *sd, int enable) | ||
702 | { | ||
703 | v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); | ||
704 | |||
705 | if (enable) | ||
706 | adv7511_wr_and_or(sd, 0x4b, 0x3f, 0x80); | ||
707 | else | ||
708 | adv7511_wr_and_or(sd, 0x4b, 0x3f, 0x40); | ||
709 | |||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | ||
714 | { | ||
715 | u32 N; | ||
716 | |||
717 | switch (freq) { | ||
718 | case 32000: N = 4096; break; | ||
719 | case 44100: N = 6272; break; | ||
720 | case 48000: N = 6144; break; | ||
721 | case 88200: N = 12544; break; | ||
722 | case 96000: N = 12288; break; | ||
723 | case 176400: N = 25088; break; | ||
724 | case 192000: N = 24576; break; | ||
725 | default: | ||
726 | return -EINVAL; | ||
727 | } | ||
728 | |||
729 | /* Set N (used with CTS to regenerate the audio clock) */ | ||
730 | adv7511_wr(sd, 0x01, (N >> 16) & 0xf); | ||
731 | adv7511_wr(sd, 0x02, (N >> 8) & 0xff); | ||
732 | adv7511_wr(sd, 0x03, N & 0xff); | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | static int adv7511_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) | ||
738 | { | ||
739 | u32 i2s_sf; | ||
740 | |||
741 | switch (freq) { | ||
742 | case 32000: i2s_sf = 0x30; break; | ||
743 | case 44100: i2s_sf = 0x00; break; | ||
744 | case 48000: i2s_sf = 0x20; break; | ||
745 | case 88200: i2s_sf = 0x80; break; | ||
746 | case 96000: i2s_sf = 0xa0; break; | ||
747 | case 176400: i2s_sf = 0xc0; break; | ||
748 | case 192000: i2s_sf = 0xe0; break; | ||
749 | default: | ||
750 | return -EINVAL; | ||
751 | } | ||
752 | |||
753 | /* Set sampling frequency for I2S audio to 48 kHz */ | ||
754 | adv7511_wr_and_or(sd, 0x15, 0xf, i2s_sf); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | static int adv7511_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) | ||
760 | { | ||
761 | /* Only 2 channels in use for application */ | ||
762 | adv7511_wr_and_or(sd, 0x73, 0xf8, 0x1); | ||
763 | /* Speaker mapping */ | ||
764 | adv7511_wr(sd, 0x76, 0x00); | ||
765 | |||
766 | /* 16 bit audio word length */ | ||
767 | adv7511_wr_and_or(sd, 0x14, 0xf0, 0x02); | ||
768 | |||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | static const struct v4l2_subdev_audio_ops adv7511_audio_ops = { | ||
773 | .s_stream = adv7511_s_audio_stream, | ||
774 | .s_clock_freq = adv7511_s_clock_freq, | ||
775 | .s_i2s_clock_freq = adv7511_s_i2s_clock_freq, | ||
776 | .s_routing = adv7511_s_routing, | ||
777 | }; | ||
778 | |||
779 | /* --------------------- SUBDEV OPS --------------------------------------- */ | ||
780 | |||
781 | static const struct v4l2_subdev_ops adv7511_ops = { | ||
782 | .core = &adv7511_core_ops, | ||
783 | .pad = &adv7511_pad_ops, | ||
784 | .video = &adv7511_video_ops, | ||
785 | .audio = &adv7511_audio_ops, | ||
786 | }; | ||
787 | |||
788 | /* ----------------------------------------------------------------------- */ | ||
789 | static void adv7511_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, int segment, uint8_t *buf) | ||
790 | { | ||
791 | if (debug >= lvl) { | ||
792 | int i, j; | ||
793 | v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment); | ||
794 | for (i = 0; i < 256; i += 16) { | ||
795 | u8 b[128]; | ||
796 | u8 *bp = b; | ||
797 | if (i == 128) | ||
798 | v4l2_dbg(lvl, debug, sd, "\n"); | ||
799 | for (j = i; j < i + 16; j++) { | ||
800 | sprintf(bp, "0x%02x, ", buf[j]); | ||
801 | bp += 6; | ||
802 | } | ||
803 | bp[0] = '\0'; | ||
804 | v4l2_dbg(lvl, debug, sd, "%s\n", b); | ||
805 | } | ||
806 | } | ||
807 | } | ||
808 | |||
809 | static void adv7511_edid_handler(struct work_struct *work) | ||
810 | { | ||
811 | struct delayed_work *dwork = to_delayed_work(work); | ||
812 | struct adv7511_state *state = container_of(dwork, struct adv7511_state, edid_handler); | ||
813 | struct v4l2_subdev *sd = &state->sd; | ||
814 | struct adv7511_edid_detect ed; | ||
815 | |||
816 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
817 | |||
818 | if (adv7511_check_edid_status(sd)) { | ||
819 | /* Return if we received the EDID. */ | ||
820 | return; | ||
821 | } | ||
822 | |||
823 | if (adv7511_have_hotplug(sd)) { | ||
824 | /* We must retry reading the EDID several times, it is possible | ||
825 | * that initially the EDID couldn't be read due to i2c errors | ||
826 | * (DVI connectors are particularly prone to this problem). */ | ||
827 | if (state->edid.read_retries) { | ||
828 | state->edid.read_retries--; | ||
829 | v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__); | ||
830 | state->have_monitor = false; | ||
831 | adv7511_s_power(sd, false); | ||
832 | adv7511_s_power(sd, true); | ||
833 | queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); | ||
834 | return; | ||
835 | } | ||
836 | } | ||
837 | |||
838 | /* We failed to read the EDID, so send an event for this. */ | ||
839 | ed.present = false; | ||
840 | ed.segment = adv7511_rd(sd, 0xc4); | ||
841 | v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); | ||
842 | v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__); | ||
843 | } | ||
844 | |||
845 | static void adv7511_audio_setup(struct v4l2_subdev *sd) | ||
846 | { | ||
847 | v4l2_dbg(1, debug, sd, "%s\n", __func__); | ||
848 | |||
849 | adv7511_s_i2s_clock_freq(sd, 48000); | ||
850 | adv7511_s_clock_freq(sd, 48000); | ||
851 | adv7511_s_routing(sd, 0, 0, 0); | ||
852 | } | ||
853 | |||
854 | /* Configure hdmi transmitter. */ | ||
855 | static void adv7511_setup(struct v4l2_subdev *sd) | ||
856 | { | ||
857 | struct adv7511_state *state = get_adv7511_state(sd); | ||
858 | v4l2_dbg(1, debug, sd, "%s\n", __func__); | ||
859 | |||
860 | /* Input format: RGB 4:4:4 */ | ||
861 | adv7511_wr_and_or(sd, 0x15, 0xf0, 0x0); | ||
862 | /* Output format: RGB 4:4:4 */ | ||
863 | adv7511_wr_and_or(sd, 0x16, 0x7f, 0x0); | ||
864 | /* 1st order interpolation 4:2:2 -> 4:4:4 up conversion, Aspect ratio: 16:9 */ | ||
865 | adv7511_wr_and_or(sd, 0x17, 0xf9, 0x06); | ||
866 | /* Disable pixel repetition */ | ||
867 | adv7511_wr_and_or(sd, 0x3b, 0x9f, 0x0); | ||
868 | /* Disable CSC */ | ||
869 | adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0); | ||
870 | /* Output format: RGB 4:4:4, Active Format Information is valid, | ||
871 | * underscanned */ | ||
872 | adv7511_wr_and_or(sd, 0x55, 0x9c, 0x12); | ||
873 | /* AVI Info frame packet enable, Audio Info frame disable */ | ||
874 | adv7511_wr_and_or(sd, 0x44, 0xe7, 0x10); | ||
875 | /* Colorimetry, Active format aspect ratio: same as picure. */ | ||
876 | adv7511_wr(sd, 0x56, 0xa8); | ||
877 | /* No encryption */ | ||
878 | adv7511_wr_and_or(sd, 0xaf, 0xed, 0x0); | ||
879 | |||
880 | /* Positive clk edge capture for input video clock */ | ||
881 | adv7511_wr_and_or(sd, 0xba, 0x1f, 0x60); | ||
882 | |||
883 | adv7511_audio_setup(sd); | ||
884 | |||
885 | v4l2_ctrl_handler_setup(&state->hdl); | ||
886 | } | ||
887 | |||
888 | static void adv7511_notify_monitor_detect(struct v4l2_subdev *sd) | ||
889 | { | ||
890 | struct adv7511_monitor_detect mdt; | ||
891 | struct adv7511_state *state = get_adv7511_state(sd); | ||
892 | |||
893 | mdt.present = state->have_monitor; | ||
894 | v4l2_subdev_notify(sd, ADV7511_MONITOR_DETECT, (void *)&mdt); | ||
895 | } | ||
896 | |||
897 | static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd) | ||
898 | { | ||
899 | struct adv7511_state *state = get_adv7511_state(sd); | ||
900 | /* read hotplug and rx-sense state */ | ||
901 | uint8_t status = adv7511_rd(sd, 0x42); | ||
902 | |||
903 | v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n", | ||
904 | __func__, | ||
905 | status, | ||
906 | status & MASK_ADV7511_HPD_DETECT ? ", hotplug" : "", | ||
907 | status & MASK_ADV7511_MSEN_DETECT ? ", rx-sense" : ""); | ||
908 | |||
909 | /* update read only ctrls */ | ||
910 | v4l2_ctrl_s_ctrl(state->hotplug_ctrl, adv7511_have_hotplug(sd) ? 0x1 : 0x0); | ||
911 | v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, adv7511_have_rx_sense(sd) ? 0x1 : 0x0); | ||
912 | v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); | ||
913 | |||
914 | if ((status & MASK_ADV7511_HPD_DETECT) && ((status & MASK_ADV7511_MSEN_DETECT) || state->edid.segments)) { | ||
915 | v4l2_dbg(1, debug, sd, "%s: hotplug and (rx-sense or edid)\n", __func__); | ||
916 | if (!state->have_monitor) { | ||
917 | v4l2_dbg(1, debug, sd, "%s: monitor detected\n", __func__); | ||
918 | state->have_monitor = true; | ||
919 | adv7511_set_isr(sd, true); | ||
920 | if (!adv7511_s_power(sd, true)) { | ||
921 | v4l2_dbg(1, debug, sd, "%s: monitor detected, powerup failed\n", __func__); | ||
922 | return; | ||
923 | } | ||
924 | adv7511_setup(sd); | ||
925 | adv7511_notify_monitor_detect(sd); | ||
926 | state->edid.read_retries = EDID_MAX_RETRIES; | ||
927 | queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); | ||
928 | } | ||
929 | } else if (status & MASK_ADV7511_HPD_DETECT) { | ||
930 | v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__); | ||
931 | state->edid.read_retries = EDID_MAX_RETRIES; | ||
932 | queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); | ||
933 | } else if (!(status & MASK_ADV7511_HPD_DETECT)) { | ||
934 | v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__); | ||
935 | if (state->have_monitor) { | ||
936 | v4l2_dbg(1, debug, sd, "%s: monitor not detected\n", __func__); | ||
937 | state->have_monitor = false; | ||
938 | adv7511_notify_monitor_detect(sd); | ||
939 | } | ||
940 | adv7511_s_power(sd, false); | ||
941 | memset(&state->edid, 0, sizeof(struct adv7511_state_edid)); | ||
942 | } | ||
943 | } | ||
944 | |||
945 | static bool edid_block_verify_crc(uint8_t *edid_block) | ||
946 | { | ||
947 | int i; | ||
948 | uint8_t sum = 0; | ||
949 | |||
950 | for (i = 0; i < 128; i++) | ||
951 | sum += *(edid_block + i); | ||
952 | return (sum == 0); | ||
953 | } | ||
954 | |||
955 | static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) | ||
956 | { | ||
957 | struct adv7511_state *state = get_adv7511_state(sd); | ||
958 | u32 blocks = state->edid.blocks; | ||
959 | uint8_t *data = state->edid.data; | ||
960 | |||
961 | if (edid_block_verify_crc(&data[segment * 256])) { | ||
962 | if ((segment + 1) * 2 <= blocks) | ||
963 | return edid_block_verify_crc(&data[segment * 256 + 128]); | ||
964 | return true; | ||
965 | } | ||
966 | return false; | ||
967 | } | ||
968 | |||
969 | static bool adv7511_check_edid_status(struct v4l2_subdev *sd) | ||
970 | { | ||
971 | struct adv7511_state *state = get_adv7511_state(sd); | ||
972 | uint8_t edidRdy = adv7511_rd(sd, 0xc5); | ||
973 | |||
974 | v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n", | ||
975 | __func__, EDID_MAX_RETRIES - state->edid.read_retries); | ||
976 | |||
977 | if (state->edid.complete) | ||
978 | return true; | ||
979 | |||
980 | if (edidRdy & MASK_ADV7511_EDID_RDY) { | ||
981 | int segment = adv7511_rd(sd, 0xc4); | ||
982 | struct adv7511_edid_detect ed; | ||
983 | |||
984 | if (segment >= EDID_MAX_SEGM) { | ||
985 | v4l2_err(sd, "edid segment number too big\n"); | ||
986 | return false; | ||
987 | } | ||
988 | v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment); | ||
989 | adv7511_edid_rd(sd, 256, &state->edid.data[segment * 256]); | ||
990 | adv7511_dbg_dump_edid(2, debug, sd, segment, &state->edid.data[segment * 256]); | ||
991 | if (segment == 0) { | ||
992 | state->edid.blocks = state->edid.data[0x7e] + 1; | ||
993 | v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n", __func__, state->edid.blocks); | ||
994 | } | ||
995 | if (!edid_segment_verify_crc(sd, segment)) { | ||
996 | /* edid crc error, force reread of edid segment */ | ||
997 | v4l2_dbg(1, debug, sd, "%s: edid crc error\n", __func__); | ||
998 | state->have_monitor = false; | ||
999 | adv7511_s_power(sd, false); | ||
1000 | adv7511_s_power(sd, true); | ||
1001 | return false; | ||
1002 | } | ||
1003 | /* one more segment read ok */ | ||
1004 | state->edid.segments = segment + 1; | ||
1005 | if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) { | ||
1006 | /* Request next EDID segment */ | ||
1007 | v4l2_dbg(1, debug, sd, "%s: request segment %d\n", __func__, state->edid.segments); | ||
1008 | adv7511_wr(sd, 0xc9, 0xf); | ||
1009 | adv7511_wr(sd, 0xc4, state->edid.segments); | ||
1010 | state->edid.read_retries = EDID_MAX_RETRIES; | ||
1011 | queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); | ||
1012 | return false; | ||
1013 | } | ||
1014 | |||
1015 | v4l2_dbg(1, debug, sd, "%s: edid complete with %d segment(s)\n", __func__, state->edid.segments); | ||
1016 | state->edid.complete = true; | ||
1017 | |||
1018 | /* report when we have all segments | ||
1019 | but report only for segment 0 | ||
1020 | */ | ||
1021 | ed.present = true; | ||
1022 | ed.segment = 0; | ||
1023 | state->edid_detect_counter++; | ||
1024 | v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); | ||
1025 | v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); | ||
1026 | return ed.present; | ||
1027 | } | ||
1028 | |||
1029 | return false; | ||
1030 | } | ||
1031 | |||
1032 | /* ----------------------------------------------------------------------- */ | ||
1033 | /* Setup ADV7511 */ | ||
1034 | static void adv7511_init_setup(struct v4l2_subdev *sd) | ||
1035 | { | ||
1036 | struct adv7511_state *state = get_adv7511_state(sd); | ||
1037 | struct adv7511_state_edid *edid = &state->edid; | ||
1038 | |||
1039 | v4l2_dbg(1, debug, sd, "%s\n", __func__); | ||
1040 | |||
1041 | /* clear all interrupts */ | ||
1042 | adv7511_wr(sd, 0x96, 0xff); | ||
1043 | memset(edid, 0, sizeof(struct adv7511_state_edid)); | ||
1044 | state->have_monitor = false; | ||
1045 | adv7511_set_isr(sd, false); | ||
1046 | adv7511_s_stream(sd, false); | ||
1047 | adv7511_s_audio_stream(sd, false); | ||
1048 | } | ||
1049 | |||
1050 | static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
1051 | { | ||
1052 | struct adv7511_state *state; | ||
1053 | struct adv7511_platform_data *pdata = client->dev.platform_data; | ||
1054 | struct v4l2_ctrl_handler *hdl; | ||
1055 | struct v4l2_subdev *sd; | ||
1056 | u8 chip_id[2]; | ||
1057 | int err = -EIO; | ||
1058 | |||
1059 | /* Check if the adapter supports the needed features */ | ||
1060 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
1061 | return -EIO; | ||
1062 | |||
1063 | state = devm_kzalloc(&client->dev, sizeof(struct adv7511_state), GFP_KERNEL); | ||
1064 | if (!state) | ||
1065 | return -ENOMEM; | ||
1066 | |||
1067 | /* Platform data */ | ||
1068 | if (!pdata) { | ||
1069 | v4l_err(client, "No platform data!\n"); | ||
1070 | return -ENODEV; | ||
1071 | } | ||
1072 | memcpy(&state->pdata, pdata, sizeof(state->pdata)); | ||
1073 | |||
1074 | sd = &state->sd; | ||
1075 | |||
1076 | v4l2_dbg(1, debug, sd, "detecting adv7511 client on address 0x%x\n", | ||
1077 | client->addr << 1); | ||
1078 | |||
1079 | v4l2_i2c_subdev_init(sd, client, &adv7511_ops); | ||
1080 | |||
1081 | hdl = &state->hdl; | ||
1082 | v4l2_ctrl_handler_init(hdl, 10); | ||
1083 | /* add in ascending ID order */ | ||
1084 | state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, | ||
1085 | V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, | ||
1086 | 0, V4L2_DV_TX_MODE_DVI_D); | ||
1087 | state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
1088 | V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0); | ||
1089 | state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
1090 | V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0); | ||
1091 | state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
1092 | V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0); | ||
1093 | state->rgb_quantization_range_ctrl = | ||
1094 | v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, | ||
1095 | V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | ||
1096 | 0, V4L2_DV_RGB_RANGE_AUTO); | ||
1097 | sd->ctrl_handler = hdl; | ||
1098 | if (hdl->error) { | ||
1099 | err = hdl->error; | ||
1100 | goto err_hdl; | ||
1101 | } | ||
1102 | state->hdmi_mode_ctrl->is_private = true; | ||
1103 | state->hotplug_ctrl->is_private = true; | ||
1104 | state->rx_sense_ctrl->is_private = true; | ||
1105 | state->have_edid0_ctrl->is_private = true; | ||
1106 | state->rgb_quantization_range_ctrl->is_private = true; | ||
1107 | |||
1108 | state->pad.flags = MEDIA_PAD_FL_SINK; | ||
1109 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | ||
1110 | if (err) | ||
1111 | goto err_hdl; | ||
1112 | |||
1113 | /* EDID and CEC i2c addr */ | ||
1114 | state->i2c_edid_addr = state->pdata.i2c_edid << 1; | ||
1115 | state->i2c_cec_addr = state->pdata.i2c_cec << 1; | ||
1116 | |||
1117 | state->chip_revision = adv7511_rd(sd, 0x0); | ||
1118 | chip_id[0] = adv7511_rd(sd, 0xf5); | ||
1119 | chip_id[1] = adv7511_rd(sd, 0xf6); | ||
1120 | if (chip_id[0] != 0x75 || chip_id[1] != 0x11) { | ||
1121 | v4l2_err(sd, "chip_id != 0x7511, read 0x%02x%02x\n", chip_id[0], chip_id[1]); | ||
1122 | err = -EIO; | ||
1123 | goto err_entity; | ||
1124 | } | ||
1125 | |||
1126 | state->i2c_edid = i2c_new_dummy(client->adapter, state->i2c_edid_addr >> 1); | ||
1127 | if (state->i2c_edid == NULL) { | ||
1128 | v4l2_err(sd, "failed to register edid i2c client\n"); | ||
1129 | goto err_entity; | ||
1130 | } | ||
1131 | |||
1132 | adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */ | ||
1133 | state->work_queue = create_singlethread_workqueue(sd->name); | ||
1134 | if (state->work_queue == NULL) { | ||
1135 | v4l2_err(sd, "could not create workqueue\n"); | ||
1136 | goto err_unreg_cec; | ||
1137 | } | ||
1138 | |||
1139 | INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler); | ||
1140 | |||
1141 | adv7511_init_setup(sd); | ||
1142 | adv7511_set_isr(sd, true); | ||
1143 | adv7511_check_monitor_present_status(sd); | ||
1144 | |||
1145 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, | ||
1146 | client->addr << 1, client->adapter->name); | ||
1147 | return 0; | ||
1148 | |||
1149 | err_unreg_cec: | ||
1150 | i2c_unregister_device(state->i2c_edid); | ||
1151 | err_entity: | ||
1152 | media_entity_cleanup(&sd->entity); | ||
1153 | err_hdl: | ||
1154 | v4l2_ctrl_handler_free(&state->hdl); | ||
1155 | return err; | ||
1156 | } | ||
1157 | |||
1158 | /* ----------------------------------------------------------------------- */ | ||
1159 | |||
1160 | static int adv7511_remove(struct i2c_client *client) | ||
1161 | { | ||
1162 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
1163 | struct adv7511_state *state = get_adv7511_state(sd); | ||
1164 | |||
1165 | state->chip_revision = -1; | ||
1166 | |||
1167 | v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, | ||
1168 | client->addr << 1, client->adapter->name); | ||
1169 | |||
1170 | adv7511_init_setup(sd); | ||
1171 | cancel_delayed_work(&state->edid_handler); | ||
1172 | i2c_unregister_device(state->i2c_edid); | ||
1173 | destroy_workqueue(state->work_queue); | ||
1174 | v4l2_device_unregister_subdev(sd); | ||
1175 | media_entity_cleanup(&sd->entity); | ||
1176 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | /* ----------------------------------------------------------------------- */ | ||
1181 | |||
1182 | static struct i2c_device_id adv7511_id[] = { | ||
1183 | { "adv7511", 0 }, | ||
1184 | { } | ||
1185 | }; | ||
1186 | MODULE_DEVICE_TABLE(i2c, adv7511_id); | ||
1187 | |||
1188 | static struct i2c_driver adv7511_driver = { | ||
1189 | .driver = { | ||
1190 | .owner = THIS_MODULE, | ||
1191 | .name = "adv7511", | ||
1192 | }, | ||
1193 | .probe = adv7511_probe, | ||
1194 | .remove = adv7511_remove, | ||
1195 | .id_table = adv7511_id, | ||
1196 | }; | ||
1197 | |||
1198 | module_i2c_driver(adv7511_driver); | ||
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 1d675b58fd71..fbfdd2fc2a36 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/v4l2-dv-timings.h> | 38 | #include <linux/v4l2-dv-timings.h> |
39 | #include <media/v4l2-device.h> | 39 | #include <media/v4l2-device.h> |
40 | #include <media/v4l2-ctrls.h> | 40 | #include <media/v4l2-ctrls.h> |
41 | #include <media/v4l2-dv-timings.h> | ||
41 | #include <media/adv7604.h> | 42 | #include <media/adv7604.h> |
42 | 43 | ||
43 | static int debug; | 44 | static int debug; |
@@ -76,6 +77,7 @@ struct adv7604_state { | |||
76 | struct delayed_work delayed_work_enable_hotplug; | 77 | struct delayed_work delayed_work_enable_hotplug; |
77 | bool connector_hdmi; | 78 | bool connector_hdmi; |
78 | bool restart_stdi_once; | 79 | bool restart_stdi_once; |
80 | u32 prev_input_status; | ||
79 | 81 | ||
80 | /* i2c clients */ | 82 | /* i2c clients */ |
81 | struct i2c_client *i2c_avlink; | 83 | struct i2c_client *i2c_avlink; |
@@ -260,22 +262,22 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | |||
260 | 262 | ||
261 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) | 263 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) |
262 | { | 264 | { |
263 | return t->hfrontporch + t->hsync + t->hbackporch; | 265 | return V4L2_DV_BT_BLANKING_WIDTH(t); |
264 | } | 266 | } |
265 | 267 | ||
266 | static inline unsigned htotal(const struct v4l2_bt_timings *t) | 268 | static inline unsigned htotal(const struct v4l2_bt_timings *t) |
267 | { | 269 | { |
268 | return t->width + t->hfrontporch + t->hsync + t->hbackporch; | 270 | return V4L2_DV_BT_FRAME_WIDTH(t); |
269 | } | 271 | } |
270 | 272 | ||
271 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) | 273 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) |
272 | { | 274 | { |
273 | return t->vfrontporch + t->vsync + t->vbackporch; | 275 | return V4L2_DV_BT_BLANKING_HEIGHT(t); |
274 | } | 276 | } |
275 | 277 | ||
276 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) | 278 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) |
277 | { | 279 | { |
278 | return t->height + t->vfrontporch + t->vsync + t->vbackporch; | 280 | return V4L2_DV_BT_FRAME_HEIGHT(t); |
279 | } | 281 | } |
280 | 282 | ||
281 | /* ----------------------------------------------------------------------- */ | 283 | /* ----------------------------------------------------------------------- */ |
@@ -761,7 +763,7 @@ static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, | |||
761 | int i; | 763 | int i; |
762 | 764 | ||
763 | for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { | 765 | for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { |
764 | if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings, | 766 | if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings, |
765 | DIGITAL_INPUT ? 250000 : 1000000)) | 767 | DIGITAL_INPUT ? 250000 : 1000000)) |
766 | continue; | 768 | continue; |
767 | io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */ | 769 | io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */ |
@@ -990,6 +992,11 @@ static inline bool no_lock_tmds(struct v4l2_subdev *sd) | |||
990 | return (io_read(sd, 0x6a) & 0xe0) != 0xe0; | 992 | return (io_read(sd, 0x6a) & 0xe0) != 0xe0; |
991 | } | 993 | } |
992 | 994 | ||
995 | static inline bool is_hdmi(struct v4l2_subdev *sd) | ||
996 | { | ||
997 | return hdmi_read(sd, 0x05) & 0x80; | ||
998 | } | ||
999 | |||
993 | static inline bool no_lock_sspd(struct v4l2_subdev *sd) | 1000 | static inline bool no_lock_sspd(struct v4l2_subdev *sd) |
994 | { | 1001 | { |
995 | /* TODO channel 2 */ | 1002 | /* TODO channel 2 */ |
@@ -1044,38 +1051,6 @@ static int adv7604_g_input_status(struct v4l2_subdev *sd, u32 *status) | |||
1044 | 1051 | ||
1045 | /* ----------------------------------------------------------------------- */ | 1052 | /* ----------------------------------------------------------------------- */ |
1046 | 1053 | ||
1047 | static void adv7604_print_timings(struct v4l2_subdev *sd, | ||
1048 | struct v4l2_dv_timings *timings, const char *txt, bool detailed) | ||
1049 | { | ||
1050 | struct v4l2_bt_timings *bt = &timings->bt; | ||
1051 | u32 htot, vtot; | ||
1052 | |||
1053 | if (timings->type != V4L2_DV_BT_656_1120) | ||
1054 | return; | ||
1055 | |||
1056 | htot = htotal(bt); | ||
1057 | vtot = vtotal(bt); | ||
1058 | |||
1059 | v4l2_info(sd, "%s %dx%d%s%d (%dx%d)", | ||
1060 | txt, bt->width, bt->height, bt->interlaced ? "i" : "p", | ||
1061 | (htot * vtot) > 0 ? ((u32)bt->pixelclock / | ||
1062 | (htot * vtot)) : 0, | ||
1063 | htot, vtot); | ||
1064 | |||
1065 | if (detailed) { | ||
1066 | v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n", | ||
1067 | bt->hfrontporch, | ||
1068 | (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", | ||
1069 | bt->hsync, bt->hbackporch); | ||
1070 | v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n", | ||
1071 | bt->vfrontporch, | ||
1072 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", | ||
1073 | bt->vsync, bt->vbackporch); | ||
1074 | v4l2_info(sd, " pixelclock: %lld, flags: 0x%x, standards: 0x%x\n", | ||
1075 | bt->pixelclock, bt->flags, bt->standards); | ||
1076 | } | ||
1077 | } | ||
1078 | |||
1079 | struct stdi_readback { | 1054 | struct stdi_readback { |
1080 | u16 bl, lcf, lcvs; | 1055 | u16 bl, lcf, lcvs; |
1081 | u8 hs_pol, vs_pol; | 1056 | u8 hs_pol, vs_pol; |
@@ -1187,7 +1162,7 @@ static int adv7604_dv_timings_cap(struct v4l2_subdev *sd, | |||
1187 | cap->type = V4L2_DV_BT_656_1120; | 1162 | cap->type = V4L2_DV_BT_656_1120; |
1188 | cap->bt.max_width = 1920; | 1163 | cap->bt.max_width = 1920; |
1189 | cap->bt.max_height = 1200; | 1164 | cap->bt.max_height = 1200; |
1190 | cap->bt.min_pixelclock = 27000000; | 1165 | cap->bt.min_pixelclock = 25000000; |
1191 | if (DIGITAL_INPUT) | 1166 | if (DIGITAL_INPUT) |
1192 | cap->bt.max_pixelclock = 225000000; | 1167 | cap->bt.max_pixelclock = 225000000; |
1193 | else | 1168 | else |
@@ -1208,7 +1183,7 @@ static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, | |||
1208 | int i; | 1183 | int i; |
1209 | 1184 | ||
1210 | for (i = 0; adv7604_timings[i].bt.width; i++) { | 1185 | for (i = 0; adv7604_timings[i].bt.width; i++) { |
1211 | if (v4l_match_dv_timings(timings, &adv7604_timings[i], | 1186 | if (v4l2_match_dv_timings(timings, &adv7604_timings[i], |
1212 | DIGITAL_INPUT ? 250000 : 1000000)) { | 1187 | DIGITAL_INPUT ? 250000 : 1000000)) { |
1213 | *timings = adv7604_timings[i]; | 1188 | *timings = adv7604_timings[i]; |
1214 | break; | 1189 | break; |
@@ -1242,12 +1217,21 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, | |||
1242 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; | 1217 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; |
1243 | 1218 | ||
1244 | if (DIGITAL_INPUT) { | 1219 | if (DIGITAL_INPUT) { |
1220 | uint32_t freq; | ||
1221 | |||
1245 | timings->type = V4L2_DV_BT_656_1120; | 1222 | timings->type = V4L2_DV_BT_656_1120; |
1246 | 1223 | ||
1247 | bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08); | 1224 | bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08); |
1248 | bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a); | 1225 | bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a); |
1249 | bt->pixelclock = (hdmi_read(sd, 0x06) * 1000000) + | 1226 | freq = (hdmi_read(sd, 0x06) * 1000000) + |
1250 | ((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000; | 1227 | ((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000; |
1228 | if (is_hdmi(sd)) { | ||
1229 | /* adjust for deep color mode */ | ||
1230 | unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8; | ||
1231 | |||
1232 | freq = freq * 8 / bits_per_channel; | ||
1233 | } | ||
1234 | bt->pixelclock = freq; | ||
1251 | bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 + | 1235 | bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 + |
1252 | hdmi_read(sd, 0x21); | 1236 | hdmi_read(sd, 0x21); |
1253 | bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 + | 1237 | bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 + |
@@ -1329,8 +1313,8 @@ found: | |||
1329 | } | 1313 | } |
1330 | 1314 | ||
1331 | if (debug > 1) | 1315 | if (debug > 1) |
1332 | adv7604_print_timings(sd, timings, | 1316 | v4l2_print_dv_timings(sd->name, "adv7604_query_dv_timings: ", |
1333 | "adv7604_query_dv_timings:", true); | 1317 | timings, true); |
1334 | 1318 | ||
1335 | return 0; | 1319 | return 0; |
1336 | } | 1320 | } |
@@ -1372,8 +1356,8 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd, | |||
1372 | 1356 | ||
1373 | 1357 | ||
1374 | if (debug > 1) | 1358 | if (debug > 1) |
1375 | adv7604_print_timings(sd, timings, | 1359 | v4l2_print_dv_timings(sd->name, "adv7604_s_dv_timings: ", |
1376 | "adv7604_s_dv_timings:", true); | 1360 | timings, true); |
1377 | return 0; | 1361 | return 0; |
1378 | } | 1362 | } |
1379 | 1363 | ||
@@ -1534,6 +1518,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | |||
1534 | { | 1518 | { |
1535 | struct adv7604_state *state = to_state(sd); | 1519 | struct adv7604_state *state = to_state(sd); |
1536 | u8 fmt_change, fmt_change_digital, tx_5v; | 1520 | u8 fmt_change, fmt_change_digital, tx_5v; |
1521 | u32 input_status; | ||
1537 | 1522 | ||
1538 | /* format change */ | 1523 | /* format change */ |
1539 | fmt_change = io_read(sd, 0x43) & 0x98; | 1524 | fmt_change = io_read(sd, 0x43) & 0x98; |
@@ -1544,9 +1529,18 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | |||
1544 | io_write(sd, 0x6c, fmt_change_digital); | 1529 | io_write(sd, 0x6c, fmt_change_digital); |
1545 | if (fmt_change || fmt_change_digital) { | 1530 | if (fmt_change || fmt_change_digital) { |
1546 | v4l2_dbg(1, debug, sd, | 1531 | v4l2_dbg(1, debug, sd, |
1547 | "%s: ADV7604_FMT_CHANGE, fmt_change = 0x%x, fmt_change_digital = 0x%x\n", | 1532 | "%s: fmt_change = 0x%x, fmt_change_digital = 0x%x\n", |
1548 | __func__, fmt_change, fmt_change_digital); | 1533 | __func__, fmt_change, fmt_change_digital); |
1549 | v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL); | 1534 | |
1535 | adv7604_g_input_status(sd, &input_status); | ||
1536 | if (input_status != state->prev_input_status) { | ||
1537 | v4l2_dbg(1, debug, sd, | ||
1538 | "%s: input_status = 0x%x, prev_input_status = 0x%x\n", | ||
1539 | __func__, input_status, state->prev_input_status); | ||
1540 | state->prev_input_status = input_status; | ||
1541 | v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL); | ||
1542 | } | ||
1543 | |||
1550 | if (handled) | 1544 | if (handled) |
1551 | *handled = true; | 1545 | *handled = true; |
1552 | } | 1546 | } |
@@ -1625,7 +1619,7 @@ static void print_avi_infoframe(struct v4l2_subdev *sd) | |||
1625 | u8 avi_len; | 1619 | u8 avi_len; |
1626 | u8 avi_ver; | 1620 | u8 avi_ver; |
1627 | 1621 | ||
1628 | if (!(hdmi_read(sd, 0x05) & 0x80)) { | 1622 | if (!is_hdmi(sd)) { |
1629 | v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n"); | 1623 | v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n"); |
1630 | return; | 1624 | return; |
1631 | } | 1625 | } |
@@ -1686,6 +1680,12 @@ static int adv7604_log_status(struct v4l2_subdev *sd) | |||
1686 | "RGB limited range (16-235)", | 1680 | "RGB limited range (16-235)", |
1687 | "RGB full range (0-255)", | 1681 | "RGB full range (0-255)", |
1688 | }; | 1682 | }; |
1683 | char *deep_color_mode_txt[4] = { | ||
1684 | "8-bits per channel", | ||
1685 | "10-bits per channel", | ||
1686 | "12-bits per channel", | ||
1687 | "16-bits per channel (not supported)" | ||
1688 | }; | ||
1689 | 1689 | ||
1690 | v4l2_info(sd, "-----Chip status-----\n"); | 1690 | v4l2_info(sd, "-----Chip status-----\n"); |
1691 | v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); | 1691 | v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); |
@@ -1723,8 +1723,13 @@ static int adv7604_log_status(struct v4l2_subdev *sd) | |||
1723 | if (adv7604_query_dv_timings(sd, &timings)) | 1723 | if (adv7604_query_dv_timings(sd, &timings)) |
1724 | v4l2_info(sd, "No video detected\n"); | 1724 | v4l2_info(sd, "No video detected\n"); |
1725 | else | 1725 | else |
1726 | adv7604_print_timings(sd, &timings, "Detected format:", true); | 1726 | v4l2_print_dv_timings(sd->name, "Detected format: ", |
1727 | adv7604_print_timings(sd, &state->timings, "Configured format:", true); | 1727 | &timings, true); |
1728 | v4l2_print_dv_timings(sd->name, "Configured format: ", | ||
1729 | &state->timings, true); | ||
1730 | |||
1731 | if (no_signal(sd)) | ||
1732 | return 0; | ||
1728 | 1733 | ||
1729 | v4l2_info(sd, "-----Color space-----\n"); | 1734 | v4l2_info(sd, "-----Color space-----\n"); |
1730 | v4l2_info(sd, "RGB quantization range ctrl: %s\n", | 1735 | v4l2_info(sd, "RGB quantization range ctrl: %s\n", |
@@ -1735,15 +1740,40 @@ static int adv7604_log_status(struct v4l2_subdev *sd) | |||
1735 | (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", | 1740 | (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", |
1736 | (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", | 1741 | (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", |
1737 | ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ? | 1742 | ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ? |
1738 | "enabled" : "disabled"); | 1743 | "enabled" : "disabled"); |
1739 | v4l2_info(sd, "Color space conversion: %s\n", | 1744 | v4l2_info(sd, "Color space conversion: %s\n", |
1740 | csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]); | 1745 | csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]); |
1741 | 1746 | ||
1742 | /* Digital video */ | 1747 | if (!DIGITAL_INPUT) |
1743 | if (DIGITAL_INPUT) { | 1748 | return 0; |
1744 | v4l2_info(sd, "-----HDMI status-----\n"); | 1749 | |
1745 | v4l2_info(sd, "HDCP encrypted content: %s\n", | 1750 | v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D"); |
1746 | hdmi_read(sd, 0x05) & 0x40 ? "true" : "false"); | 1751 | v4l2_info(sd, "HDCP encrypted content: %s\n", (hdmi_read(sd, 0x05) & 0x40) ? "true" : "false"); |
1752 | v4l2_info(sd, "HDCP keys read: %s%s\n", | ||
1753 | (hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no", | ||
1754 | (hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : ""); | ||
1755 | if (!is_hdmi(sd)) { | ||
1756 | bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01; | ||
1757 | bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01; | ||
1758 | bool audio_mute = io_read(sd, 0x65) & 0x40; | ||
1759 | |||
1760 | v4l2_info(sd, "Audio: pll %s, samples %s, %s\n", | ||
1761 | audio_pll_locked ? "locked" : "not locked", | ||
1762 | audio_sample_packet_detect ? "detected" : "not detected", | ||
1763 | audio_mute ? "muted" : "enabled"); | ||
1764 | if (audio_pll_locked && audio_sample_packet_detect) { | ||
1765 | v4l2_info(sd, "Audio format: %s\n", | ||
1766 | (hdmi_read(sd, 0x07) & 0x20) ? "multi-channel" : "stereo"); | ||
1767 | } | ||
1768 | v4l2_info(sd, "Audio CTS: %u\n", (hdmi_read(sd, 0x5b) << 12) + | ||
1769 | (hdmi_read(sd, 0x5c) << 8) + | ||
1770 | (hdmi_read(sd, 0x5d) & 0xf0)); | ||
1771 | v4l2_info(sd, "Audio N: %u\n", ((hdmi_read(sd, 0x5d) & 0x0f) << 16) + | ||
1772 | (hdmi_read(sd, 0x5e) << 8) + | ||
1773 | hdmi_read(sd, 0x5f)); | ||
1774 | v4l2_info(sd, "AV Mute: %s\n", (hdmi_read(sd, 0x04) & 0x40) ? "on" : "off"); | ||
1775 | |||
1776 | v4l2_info(sd, "Deep color mode: %s\n", deep_color_mode_txt[(hdmi_read(sd, 0x0b) & 0x60) >> 5]); | ||
1747 | 1777 | ||
1748 | print_avi_infoframe(sd); | 1778 | print_avi_infoframe(sd); |
1749 | } | 1779 | } |
@@ -1952,6 +1982,10 @@ static int adv7604_probe(struct i2c_client *client, | |||
1952 | return -ENOMEM; | 1982 | return -ENOMEM; |
1953 | } | 1983 | } |
1954 | 1984 | ||
1985 | /* initialize variables */ | ||
1986 | state->restart_stdi_once = true; | ||
1987 | state->prev_input_status = ~0; | ||
1988 | |||
1955 | /* platform data */ | 1989 | /* platform data */ |
1956 | if (!pdata) { | 1990 | if (!pdata) { |
1957 | v4l_err(client, "No platform data!\n"); | 1991 | v4l_err(client, "No platform data!\n"); |
@@ -1987,29 +2021,30 @@ static int adv7604_probe(struct i2c_client *client, | |||
1987 | /* private controls */ | 2021 | /* private controls */ |
1988 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 2022 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
1989 | V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); | 2023 | V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); |
1990 | state->detect_tx_5v_ctrl->is_private = true; | ||
1991 | state->rgb_quantization_range_ctrl = | 2024 | state->rgb_quantization_range_ctrl = |
1992 | v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops, | 2025 | v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops, |
1993 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | 2026 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, |
1994 | 0, V4L2_DV_RGB_RANGE_AUTO); | 2027 | 0, V4L2_DV_RGB_RANGE_AUTO); |
1995 | state->rgb_quantization_range_ctrl->is_private = true; | ||
1996 | 2028 | ||
1997 | /* custom controls */ | 2029 | /* custom controls */ |
1998 | state->analog_sampling_phase_ctrl = | 2030 | state->analog_sampling_phase_ctrl = |
1999 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL); | 2031 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL); |
2000 | state->analog_sampling_phase_ctrl->is_private = true; | ||
2001 | state->free_run_color_manual_ctrl = | 2032 | state->free_run_color_manual_ctrl = |
2002 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL); | 2033 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL); |
2003 | state->free_run_color_manual_ctrl->is_private = true; | ||
2004 | state->free_run_color_ctrl = | 2034 | state->free_run_color_ctrl = |
2005 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL); | 2035 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL); |
2006 | state->free_run_color_ctrl->is_private = true; | ||
2007 | 2036 | ||
2008 | sd->ctrl_handler = hdl; | 2037 | sd->ctrl_handler = hdl; |
2009 | if (hdl->error) { | 2038 | if (hdl->error) { |
2010 | err = hdl->error; | 2039 | err = hdl->error; |
2011 | goto err_hdl; | 2040 | goto err_hdl; |
2012 | } | 2041 | } |
2042 | state->detect_tx_5v_ctrl->is_private = true; | ||
2043 | state->rgb_quantization_range_ctrl->is_private = true; | ||
2044 | state->analog_sampling_phase_ctrl->is_private = true; | ||
2045 | state->free_run_color_manual_ctrl->is_private = true; | ||
2046 | state->free_run_color_ctrl->is_private = true; | ||
2047 | |||
2013 | if (adv7604_s_detect_tx_5v_ctrl(sd)) { | 2048 | if (adv7604_s_detect_tx_5v_ctrl(sd)) { |
2014 | err = -ENODEV; | 2049 | err = -ENODEV; |
2015 | goto err_hdl; | 2050 | goto err_hdl; |
@@ -2035,7 +2070,6 @@ static int adv7604_probe(struct i2c_client *client, | |||
2035 | v4l2_err(sd, "failed to create all i2c clients\n"); | 2070 | v4l2_err(sd, "failed to create all i2c clients\n"); |
2036 | goto err_i2c; | 2071 | goto err_i2c; |
2037 | } | 2072 | } |
2038 | state->restart_stdi_once = true; | ||
2039 | 2073 | ||
2040 | /* work queues */ | 2074 | /* work queues */ |
2041 | state->work_queues = create_singlethread_workqueue(client->name); | 2075 | state->work_queues = create_singlethread_workqueue(client->name); |
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c new file mode 100644 index 000000000000..d1748901337c --- /dev/null +++ b/drivers/media/i2c/adv7842.c | |||
@@ -0,0 +1,2946 @@ | |||
1 | /* | ||
2 | * adv7842 - Analog Devices ADV7842 video decoder driver | ||
3 | * | ||
4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you may redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
17 | * SOFTWARE. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * References (c = chapter, p = page): | ||
23 | * REF_01 - Analog devices, ADV7842, Register Settings Recommendations, | ||
24 | * Revision 2.5, June 2010 | ||
25 | * REF_02 - Analog devices, Register map documentation, Documentation of | ||
26 | * the register maps, Software manual, Rev. F, June 2010 | ||
27 | */ | ||
28 | |||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/i2c.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/videodev2.h> | ||
36 | #include <linux/workqueue.h> | ||
37 | #include <linux/v4l2-dv-timings.h> | ||
38 | #include <media/v4l2-device.h> | ||
39 | #include <media/v4l2-ctrls.h> | ||
40 | #include <media/v4l2-dv-timings.h> | ||
41 | #include <media/adv7842.h> | ||
42 | |||
43 | static int debug; | ||
44 | module_param(debug, int, 0644); | ||
45 | MODULE_PARM_DESC(debug, "debug level (0-2)"); | ||
46 | |||
47 | MODULE_DESCRIPTION("Analog Devices ADV7842 video decoder driver"); | ||
48 | MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); | ||
49 | MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>"); | ||
50 | MODULE_LICENSE("GPL"); | ||
51 | |||
52 | /* ADV7842 system clock frequency */ | ||
53 | #define ADV7842_fsc (28636360) | ||
54 | |||
55 | /* | ||
56 | ********************************************************************** | ||
57 | * | ||
58 | * Arrays with configuration parameters for the ADV7842 | ||
59 | * | ||
60 | ********************************************************************** | ||
61 | */ | ||
62 | |||
63 | struct adv7842_state { | ||
64 | struct v4l2_subdev sd; | ||
65 | struct media_pad pad; | ||
66 | struct v4l2_ctrl_handler hdl; | ||
67 | enum adv7842_mode mode; | ||
68 | struct v4l2_dv_timings timings; | ||
69 | enum adv7842_vid_std_select vid_std_select; | ||
70 | v4l2_std_id norm; | ||
71 | struct { | ||
72 | u8 edid[256]; | ||
73 | u32 present; | ||
74 | } hdmi_edid; | ||
75 | struct { | ||
76 | u8 edid[256]; | ||
77 | u32 present; | ||
78 | } vga_edid; | ||
79 | struct v4l2_fract aspect_ratio; | ||
80 | u32 rgb_quantization_range; | ||
81 | bool is_cea_format; | ||
82 | struct workqueue_struct *work_queues; | ||
83 | struct delayed_work delayed_work_enable_hotplug; | ||
84 | bool connector_hdmi; | ||
85 | bool hdmi_port_a; | ||
86 | |||
87 | /* i2c clients */ | ||
88 | struct i2c_client *i2c_sdp_io; | ||
89 | struct i2c_client *i2c_sdp; | ||
90 | struct i2c_client *i2c_cp; | ||
91 | struct i2c_client *i2c_vdp; | ||
92 | struct i2c_client *i2c_afe; | ||
93 | struct i2c_client *i2c_hdmi; | ||
94 | struct i2c_client *i2c_repeater; | ||
95 | struct i2c_client *i2c_edid; | ||
96 | struct i2c_client *i2c_infoframe; | ||
97 | struct i2c_client *i2c_cec; | ||
98 | struct i2c_client *i2c_avlink; | ||
99 | |||
100 | /* controls */ | ||
101 | struct v4l2_ctrl *detect_tx_5v_ctrl; | ||
102 | struct v4l2_ctrl *analog_sampling_phase_ctrl; | ||
103 | struct v4l2_ctrl *free_run_color_ctrl_manual; | ||
104 | struct v4l2_ctrl *free_run_color_ctrl; | ||
105 | struct v4l2_ctrl *rgb_quantization_range_ctrl; | ||
106 | }; | ||
107 | |||
108 | /* Unsupported timings. This device cannot support 720p30. */ | ||
109 | static const struct v4l2_dv_timings adv7842_timings_exceptions[] = { | ||
110 | V4L2_DV_BT_CEA_1280X720P30, | ||
111 | { } | ||
112 | }; | ||
113 | |||
114 | static bool adv7842_check_dv_timings(const struct v4l2_dv_timings *t, void *hdl) | ||
115 | { | ||
116 | int i; | ||
117 | |||
118 | for (i = 0; adv7842_timings_exceptions[i].bt.width; i++) | ||
119 | if (v4l2_match_dv_timings(t, adv7842_timings_exceptions + i, 0)) | ||
120 | return false; | ||
121 | return true; | ||
122 | } | ||
123 | |||
124 | struct adv7842_video_standards { | ||
125 | struct v4l2_dv_timings timings; | ||
126 | u8 vid_std; | ||
127 | u8 v_freq; | ||
128 | }; | ||
129 | |||
130 | /* sorted by number of lines */ | ||
131 | static const struct adv7842_video_standards adv7842_prim_mode_comp[] = { | ||
132 | /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */ | ||
133 | { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 }, | ||
134 | { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 }, | ||
135 | { V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 }, | ||
136 | { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 }, | ||
137 | { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 }, | ||
138 | { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 }, | ||
139 | { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 }, | ||
140 | { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 }, | ||
141 | /* TODO add 1920x1080P60_RB (CVT timing) */ | ||
142 | { }, | ||
143 | }; | ||
144 | |||
145 | /* sorted by number of lines */ | ||
146 | static const struct adv7842_video_standards adv7842_prim_mode_gr[] = { | ||
147 | { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 }, | ||
148 | { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 }, | ||
149 | { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 }, | ||
150 | { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 }, | ||
151 | { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 }, | ||
152 | { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 }, | ||
153 | { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 }, | ||
154 | { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 }, | ||
155 | { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 }, | ||
156 | { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 }, | ||
157 | { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 }, | ||
158 | { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 }, | ||
159 | { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 }, | ||
160 | { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 }, | ||
161 | { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 }, | ||
162 | { V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 }, | ||
163 | { V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 }, | ||
164 | { V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 }, | ||
165 | { V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 }, | ||
166 | { V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */ | ||
167 | /* TODO add 1600X1200P60_RB (not a DMT timing) */ | ||
168 | { V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 }, | ||
169 | { V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */ | ||
170 | { }, | ||
171 | }; | ||
172 | |||
173 | /* sorted by number of lines */ | ||
174 | static const struct adv7842_video_standards adv7842_prim_mode_hdmi_comp[] = { | ||
175 | { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, | ||
176 | { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 }, | ||
177 | { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 }, | ||
178 | { V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 }, | ||
179 | { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 }, | ||
180 | { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 }, | ||
181 | { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 }, | ||
182 | { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 }, | ||
183 | { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 }, | ||
184 | { }, | ||
185 | }; | ||
186 | |||
187 | /* sorted by number of lines */ | ||
188 | static const struct adv7842_video_standards adv7842_prim_mode_hdmi_gr[] = { | ||
189 | { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 }, | ||
190 | { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 }, | ||
191 | { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 }, | ||
192 | { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 }, | ||
193 | { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 }, | ||
194 | { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 }, | ||
195 | { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 }, | ||
196 | { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 }, | ||
197 | { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 }, | ||
198 | { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 }, | ||
199 | { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 }, | ||
200 | { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 }, | ||
201 | { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 }, | ||
202 | { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 }, | ||
203 | { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 }, | ||
204 | { }, | ||
205 | }; | ||
206 | |||
207 | /* ----------------------------------------------------------------------- */ | ||
208 | |||
209 | static inline struct adv7842_state *to_state(struct v4l2_subdev *sd) | ||
210 | { | ||
211 | return container_of(sd, struct adv7842_state, sd); | ||
212 | } | ||
213 | |||
214 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | ||
215 | { | ||
216 | return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd; | ||
217 | } | ||
218 | |||
219 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) | ||
220 | { | ||
221 | return V4L2_DV_BT_BLANKING_WIDTH(t); | ||
222 | } | ||
223 | |||
224 | static inline unsigned htotal(const struct v4l2_bt_timings *t) | ||
225 | { | ||
226 | return V4L2_DV_BT_FRAME_WIDTH(t); | ||
227 | } | ||
228 | |||
229 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) | ||
230 | { | ||
231 | return V4L2_DV_BT_BLANKING_HEIGHT(t); | ||
232 | } | ||
233 | |||
234 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) | ||
235 | { | ||
236 | return V4L2_DV_BT_FRAME_HEIGHT(t); | ||
237 | } | ||
238 | |||
239 | |||
240 | /* ----------------------------------------------------------------------- */ | ||
241 | |||
242 | static s32 adv_smbus_read_byte_data_check(struct i2c_client *client, | ||
243 | u8 command, bool check) | ||
244 | { | ||
245 | union i2c_smbus_data data; | ||
246 | |||
247 | if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
248 | I2C_SMBUS_READ, command, | ||
249 | I2C_SMBUS_BYTE_DATA, &data)) | ||
250 | return data.byte; | ||
251 | if (check) | ||
252 | v4l_err(client, "error reading %02x, %02x\n", | ||
253 | client->addr, command); | ||
254 | return -EIO; | ||
255 | } | ||
256 | |||
257 | static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command) | ||
258 | { | ||
259 | int i; | ||
260 | |||
261 | for (i = 0; i < 3; i++) { | ||
262 | int ret = adv_smbus_read_byte_data_check(client, command, true); | ||
263 | |||
264 | if (ret >= 0) { | ||
265 | if (i) | ||
266 | v4l_err(client, "read ok after %d retries\n", i); | ||
267 | return ret; | ||
268 | } | ||
269 | } | ||
270 | v4l_err(client, "read failed\n"); | ||
271 | return -EIO; | ||
272 | } | ||
273 | |||
274 | static s32 adv_smbus_write_byte_data(struct i2c_client *client, | ||
275 | u8 command, u8 value) | ||
276 | { | ||
277 | union i2c_smbus_data data; | ||
278 | int err; | ||
279 | int i; | ||
280 | |||
281 | data.byte = value; | ||
282 | for (i = 0; i < 3; i++) { | ||
283 | err = i2c_smbus_xfer(client->adapter, client->addr, | ||
284 | client->flags, | ||
285 | I2C_SMBUS_WRITE, command, | ||
286 | I2C_SMBUS_BYTE_DATA, &data); | ||
287 | if (!err) | ||
288 | break; | ||
289 | } | ||
290 | if (err < 0) | ||
291 | v4l_err(client, "error writing %02x, %02x, %02x\n", | ||
292 | client->addr, command, value); | ||
293 | return err; | ||
294 | } | ||
295 | |||
296 | static void adv_smbus_write_byte_no_check(struct i2c_client *client, | ||
297 | u8 command, u8 value) | ||
298 | { | ||
299 | union i2c_smbus_data data; | ||
300 | data.byte = value; | ||
301 | |||
302 | i2c_smbus_xfer(client->adapter, client->addr, | ||
303 | client->flags, | ||
304 | I2C_SMBUS_WRITE, command, | ||
305 | I2C_SMBUS_BYTE_DATA, &data); | ||
306 | } | ||
307 | |||
308 | static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client, | ||
309 | u8 command, unsigned length, const u8 *values) | ||
310 | { | ||
311 | union i2c_smbus_data data; | ||
312 | |||
313 | if (length > I2C_SMBUS_BLOCK_MAX) | ||
314 | length = I2C_SMBUS_BLOCK_MAX; | ||
315 | data.block[0] = length; | ||
316 | memcpy(data.block + 1, values, length); | ||
317 | return i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
318 | I2C_SMBUS_WRITE, command, | ||
319 | I2C_SMBUS_I2C_BLOCK_DATA, &data); | ||
320 | } | ||
321 | |||
322 | /* ----------------------------------------------------------------------- */ | ||
323 | |||
324 | static inline int io_read(struct v4l2_subdev *sd, u8 reg) | ||
325 | { | ||
326 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
327 | |||
328 | return adv_smbus_read_byte_data(client, reg); | ||
329 | } | ||
330 | |||
331 | static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
332 | { | ||
333 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
334 | |||
335 | return adv_smbus_write_byte_data(client, reg, val); | ||
336 | } | ||
337 | |||
338 | static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
339 | { | ||
340 | return io_write(sd, reg, (io_read(sd, reg) & mask) | val); | ||
341 | } | ||
342 | |||
343 | static inline int avlink_read(struct v4l2_subdev *sd, u8 reg) | ||
344 | { | ||
345 | struct adv7842_state *state = to_state(sd); | ||
346 | |||
347 | return adv_smbus_read_byte_data(state->i2c_avlink, reg); | ||
348 | } | ||
349 | |||
350 | static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
351 | { | ||
352 | struct adv7842_state *state = to_state(sd); | ||
353 | |||
354 | return adv_smbus_write_byte_data(state->i2c_avlink, reg, val); | ||
355 | } | ||
356 | |||
357 | static inline int cec_read(struct v4l2_subdev *sd, u8 reg) | ||
358 | { | ||
359 | struct adv7842_state *state = to_state(sd); | ||
360 | |||
361 | return adv_smbus_read_byte_data(state->i2c_cec, reg); | ||
362 | } | ||
363 | |||
364 | static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
365 | { | ||
366 | struct adv7842_state *state = to_state(sd); | ||
367 | |||
368 | return adv_smbus_write_byte_data(state->i2c_cec, reg, val); | ||
369 | } | ||
370 | |||
371 | static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
372 | { | ||
373 | return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val); | ||
374 | } | ||
375 | |||
376 | static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg) | ||
377 | { | ||
378 | struct adv7842_state *state = to_state(sd); | ||
379 | |||
380 | return adv_smbus_read_byte_data(state->i2c_infoframe, reg); | ||
381 | } | ||
382 | |||
383 | static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
384 | { | ||
385 | struct adv7842_state *state = to_state(sd); | ||
386 | |||
387 | return adv_smbus_write_byte_data(state->i2c_infoframe, reg, val); | ||
388 | } | ||
389 | |||
390 | static inline int sdp_io_read(struct v4l2_subdev *sd, u8 reg) | ||
391 | { | ||
392 | struct adv7842_state *state = to_state(sd); | ||
393 | |||
394 | return adv_smbus_read_byte_data(state->i2c_sdp_io, reg); | ||
395 | } | ||
396 | |||
397 | static inline int sdp_io_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
398 | { | ||
399 | struct adv7842_state *state = to_state(sd); | ||
400 | |||
401 | return adv_smbus_write_byte_data(state->i2c_sdp_io, reg, val); | ||
402 | } | ||
403 | |||
404 | static inline int sdp_io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
405 | { | ||
406 | return sdp_io_write(sd, reg, (sdp_io_read(sd, reg) & mask) | val); | ||
407 | } | ||
408 | |||
409 | static inline int sdp_read(struct v4l2_subdev *sd, u8 reg) | ||
410 | { | ||
411 | struct adv7842_state *state = to_state(sd); | ||
412 | |||
413 | return adv_smbus_read_byte_data(state->i2c_sdp, reg); | ||
414 | } | ||
415 | |||
416 | static inline int sdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
417 | { | ||
418 | struct adv7842_state *state = to_state(sd); | ||
419 | |||
420 | return adv_smbus_write_byte_data(state->i2c_sdp, reg, val); | ||
421 | } | ||
422 | |||
423 | static inline int sdp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
424 | { | ||
425 | return sdp_write(sd, reg, (sdp_read(sd, reg) & mask) | val); | ||
426 | } | ||
427 | |||
428 | static inline int afe_read(struct v4l2_subdev *sd, u8 reg) | ||
429 | { | ||
430 | struct adv7842_state *state = to_state(sd); | ||
431 | |||
432 | return adv_smbus_read_byte_data(state->i2c_afe, reg); | ||
433 | } | ||
434 | |||
435 | static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
436 | { | ||
437 | struct adv7842_state *state = to_state(sd); | ||
438 | |||
439 | return adv_smbus_write_byte_data(state->i2c_afe, reg, val); | ||
440 | } | ||
441 | |||
442 | static inline int afe_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
443 | { | ||
444 | return afe_write(sd, reg, (afe_read(sd, reg) & mask) | val); | ||
445 | } | ||
446 | |||
447 | static inline int rep_read(struct v4l2_subdev *sd, u8 reg) | ||
448 | { | ||
449 | struct adv7842_state *state = to_state(sd); | ||
450 | |||
451 | return adv_smbus_read_byte_data(state->i2c_repeater, reg); | ||
452 | } | ||
453 | |||
454 | static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
455 | { | ||
456 | struct adv7842_state *state = to_state(sd); | ||
457 | |||
458 | return adv_smbus_write_byte_data(state->i2c_repeater, reg, val); | ||
459 | } | ||
460 | |||
461 | static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
462 | { | ||
463 | return rep_write(sd, reg, (rep_read(sd, reg) & mask) | val); | ||
464 | } | ||
465 | |||
466 | static inline int edid_read(struct v4l2_subdev *sd, u8 reg) | ||
467 | { | ||
468 | struct adv7842_state *state = to_state(sd); | ||
469 | |||
470 | return adv_smbus_read_byte_data(state->i2c_edid, reg); | ||
471 | } | ||
472 | |||
473 | static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
474 | { | ||
475 | struct adv7842_state *state = to_state(sd); | ||
476 | |||
477 | return adv_smbus_write_byte_data(state->i2c_edid, reg, val); | ||
478 | } | ||
479 | |||
480 | static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg) | ||
481 | { | ||
482 | struct adv7842_state *state = to_state(sd); | ||
483 | |||
484 | return adv_smbus_read_byte_data(state->i2c_hdmi, reg); | ||
485 | } | ||
486 | |||
487 | static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
488 | { | ||
489 | struct adv7842_state *state = to_state(sd); | ||
490 | |||
491 | return adv_smbus_write_byte_data(state->i2c_hdmi, reg, val); | ||
492 | } | ||
493 | |||
494 | static inline int cp_read(struct v4l2_subdev *sd, u8 reg) | ||
495 | { | ||
496 | struct adv7842_state *state = to_state(sd); | ||
497 | |||
498 | return adv_smbus_read_byte_data(state->i2c_cp, reg); | ||
499 | } | ||
500 | |||
501 | static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
502 | { | ||
503 | struct adv7842_state *state = to_state(sd); | ||
504 | |||
505 | return adv_smbus_write_byte_data(state->i2c_cp, reg, val); | ||
506 | } | ||
507 | |||
508 | static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
509 | { | ||
510 | return cp_write(sd, reg, (cp_read(sd, reg) & mask) | val); | ||
511 | } | ||
512 | |||
513 | static inline int vdp_read(struct v4l2_subdev *sd, u8 reg) | ||
514 | { | ||
515 | struct adv7842_state *state = to_state(sd); | ||
516 | |||
517 | return adv_smbus_read_byte_data(state->i2c_vdp, reg); | ||
518 | } | ||
519 | |||
520 | static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
521 | { | ||
522 | struct adv7842_state *state = to_state(sd); | ||
523 | |||
524 | return adv_smbus_write_byte_data(state->i2c_vdp, reg, val); | ||
525 | } | ||
526 | |||
527 | static void main_reset(struct v4l2_subdev *sd) | ||
528 | { | ||
529 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
530 | |||
531 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
532 | |||
533 | adv_smbus_write_byte_no_check(client, 0xff, 0x80); | ||
534 | |||
535 | mdelay(2); | ||
536 | } | ||
537 | |||
538 | /* ----------------------------------------------------------------------- */ | ||
539 | |||
540 | static inline bool is_digital_input(struct v4l2_subdev *sd) | ||
541 | { | ||
542 | struct adv7842_state *state = to_state(sd); | ||
543 | |||
544 | return state->mode == ADV7842_MODE_HDMI; | ||
545 | } | ||
546 | |||
547 | static const struct v4l2_dv_timings_cap adv7842_timings_cap_analog = { | ||
548 | .type = V4L2_DV_BT_656_1120, | ||
549 | .bt = { | ||
550 | .max_width = 1920, | ||
551 | .max_height = 1200, | ||
552 | .min_pixelclock = 25000000, | ||
553 | .max_pixelclock = 170000000, | ||
554 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
555 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, | ||
556 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
557 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, | ||
558 | }, | ||
559 | }; | ||
560 | |||
561 | static const struct v4l2_dv_timings_cap adv7842_timings_cap_digital = { | ||
562 | .type = V4L2_DV_BT_656_1120, | ||
563 | .bt = { | ||
564 | .max_width = 1920, | ||
565 | .max_height = 1200, | ||
566 | .min_pixelclock = 25000000, | ||
567 | .max_pixelclock = 225000000, | ||
568 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
569 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, | ||
570 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
571 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, | ||
572 | }, | ||
573 | }; | ||
574 | |||
575 | static inline const struct v4l2_dv_timings_cap * | ||
576 | adv7842_get_dv_timings_cap(struct v4l2_subdev *sd) | ||
577 | { | ||
578 | return is_digital_input(sd) ? &adv7842_timings_cap_digital : | ||
579 | &adv7842_timings_cap_analog; | ||
580 | } | ||
581 | |||
582 | /* ----------------------------------------------------------------------- */ | ||
583 | |||
584 | static void adv7842_delayed_work_enable_hotplug(struct work_struct *work) | ||
585 | { | ||
586 | struct delayed_work *dwork = to_delayed_work(work); | ||
587 | struct adv7842_state *state = container_of(dwork, | ||
588 | struct adv7842_state, delayed_work_enable_hotplug); | ||
589 | struct v4l2_subdev *sd = &state->sd; | ||
590 | int present = state->hdmi_edid.present; | ||
591 | u8 mask = 0; | ||
592 | |||
593 | v4l2_dbg(2, debug, sd, "%s: enable hotplug on ports: 0x%x\n", | ||
594 | __func__, present); | ||
595 | |||
596 | if (present & 0x1) | ||
597 | mask |= 0x20; /* port A */ | ||
598 | if (present & 0x2) | ||
599 | mask |= 0x10; /* port B */ | ||
600 | io_write_and_or(sd, 0x20, 0xcf, mask); | ||
601 | } | ||
602 | |||
603 | static int edid_write_vga_segment(struct v4l2_subdev *sd) | ||
604 | { | ||
605 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
606 | struct adv7842_state *state = to_state(sd); | ||
607 | const u8 *val = state->vga_edid.edid; | ||
608 | int err = 0; | ||
609 | int i; | ||
610 | |||
611 | v4l2_dbg(2, debug, sd, "%s: write EDID on VGA port\n", __func__); | ||
612 | |||
613 | /* HPA disable on port A and B */ | ||
614 | io_write_and_or(sd, 0x20, 0xcf, 0x00); | ||
615 | |||
616 | /* Disable I2C access to internal EDID ram from VGA DDC port */ | ||
617 | rep_write_and_or(sd, 0x7f, 0x7f, 0x00); | ||
618 | |||
619 | /* edid segment pointer '1' for VGA port */ | ||
620 | rep_write_and_or(sd, 0x77, 0xef, 0x10); | ||
621 | |||
622 | for (i = 0; !err && i < 256; i += I2C_SMBUS_BLOCK_MAX) | ||
623 | err = adv_smbus_write_i2c_block_data(state->i2c_edid, i, | ||
624 | I2C_SMBUS_BLOCK_MAX, val + i); | ||
625 | if (err) | ||
626 | return err; | ||
627 | |||
628 | /* Calculates the checksums and enables I2C access | ||
629 | * to internal EDID ram from VGA DDC port. | ||
630 | */ | ||
631 | rep_write_and_or(sd, 0x7f, 0x7f, 0x80); | ||
632 | |||
633 | for (i = 0; i < 1000; i++) { | ||
634 | if (rep_read(sd, 0x79) & 0x20) | ||
635 | break; | ||
636 | mdelay(1); | ||
637 | } | ||
638 | if (i == 1000) { | ||
639 | v4l_err(client, "error enabling edid on VGA port\n"); | ||
640 | return -EIO; | ||
641 | } | ||
642 | |||
643 | /* enable hotplug after 200 ms */ | ||
644 | queue_delayed_work(state->work_queues, | ||
645 | &state->delayed_work_enable_hotplug, HZ / 5); | ||
646 | |||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | static int edid_spa_location(const u8 *edid) | ||
651 | { | ||
652 | u8 d; | ||
653 | |||
654 | /* | ||
655 | * TODO, improve and update for other CEA extensions | ||
656 | * currently only for 1 segment (256 bytes), | ||
657 | * i.e. 1 extension block and CEA revision 3. | ||
658 | */ | ||
659 | if ((edid[0x7e] != 1) || | ||
660 | (edid[0x80] != 0x02) || | ||
661 | (edid[0x81] != 0x03)) { | ||
662 | return -EINVAL; | ||
663 | } | ||
664 | /* | ||
665 | * search Vendor Specific Data Block (tag 3) | ||
666 | */ | ||
667 | d = edid[0x82] & 0x7f; | ||
668 | if (d > 4) { | ||
669 | int i = 0x84; | ||
670 | int end = 0x80 + d; | ||
671 | do { | ||
672 | u8 tag = edid[i]>>5; | ||
673 | u8 len = edid[i] & 0x1f; | ||
674 | |||
675 | if ((tag == 3) && (len >= 5)) | ||
676 | return i + 4; | ||
677 | i += len + 1; | ||
678 | } while (i < end); | ||
679 | } | ||
680 | return -EINVAL; | ||
681 | } | ||
682 | |||
683 | static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port) | ||
684 | { | ||
685 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
686 | struct adv7842_state *state = to_state(sd); | ||
687 | const u8 *val = state->hdmi_edid.edid; | ||
688 | u8 cur_mask = rep_read(sd, 0x77) & 0x0c; | ||
689 | u8 mask = port == 0 ? 0x4 : 0x8; | ||
690 | int spa_loc = edid_spa_location(val); | ||
691 | int err = 0; | ||
692 | int i; | ||
693 | |||
694 | v4l2_dbg(2, debug, sd, "%s: write EDID on port %d (spa at 0x%x)\n", | ||
695 | __func__, port, spa_loc); | ||
696 | |||
697 | /* HPA disable on port A and B */ | ||
698 | io_write_and_or(sd, 0x20, 0xcf, 0x00); | ||
699 | |||
700 | /* Disable I2C access to internal EDID ram from HDMI DDC ports */ | ||
701 | rep_write_and_or(sd, 0x77, 0xf3, 0x00); | ||
702 | |||
703 | /* edid segment pointer '0' for HDMI ports */ | ||
704 | rep_write_and_or(sd, 0x77, 0xef, 0x00); | ||
705 | |||
706 | for (i = 0; !err && i < 256; i += I2C_SMBUS_BLOCK_MAX) | ||
707 | err = adv_smbus_write_i2c_block_data(state->i2c_edid, i, | ||
708 | I2C_SMBUS_BLOCK_MAX, val + i); | ||
709 | if (err) | ||
710 | return err; | ||
711 | |||
712 | if (spa_loc > 0) { | ||
713 | if (port == 0) { | ||
714 | /* port A SPA */ | ||
715 | rep_write(sd, 0x72, val[spa_loc]); | ||
716 | rep_write(sd, 0x73, val[spa_loc + 1]); | ||
717 | } else { | ||
718 | /* port B SPA */ | ||
719 | rep_write(sd, 0x74, val[spa_loc]); | ||
720 | rep_write(sd, 0x75, val[spa_loc + 1]); | ||
721 | } | ||
722 | rep_write(sd, 0x76, spa_loc); | ||
723 | } else { | ||
724 | /* default register values for SPA */ | ||
725 | if (port == 0) { | ||
726 | /* port A SPA */ | ||
727 | rep_write(sd, 0x72, 0); | ||
728 | rep_write(sd, 0x73, 0); | ||
729 | } else { | ||
730 | /* port B SPA */ | ||
731 | rep_write(sd, 0x74, 0); | ||
732 | rep_write(sd, 0x75, 0); | ||
733 | } | ||
734 | rep_write(sd, 0x76, 0xc0); | ||
735 | } | ||
736 | rep_write_and_or(sd, 0x77, 0xbf, 0x00); | ||
737 | |||
738 | /* Calculates the checksums and enables I2C access to internal | ||
739 | * EDID ram from HDMI DDC ports | ||
740 | */ | ||
741 | rep_write_and_or(sd, 0x77, 0xf3, mask | cur_mask); | ||
742 | |||
743 | for (i = 0; i < 1000; i++) { | ||
744 | if (rep_read(sd, 0x7d) & mask) | ||
745 | break; | ||
746 | mdelay(1); | ||
747 | } | ||
748 | if (i == 1000) { | ||
749 | v4l_err(client, "error enabling edid on port %d\n", port); | ||
750 | return -EIO; | ||
751 | } | ||
752 | |||
753 | /* enable hotplug after 200 ms */ | ||
754 | queue_delayed_work(state->work_queues, | ||
755 | &state->delayed_work_enable_hotplug, HZ / 5); | ||
756 | |||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | /* ----------------------------------------------------------------------- */ | ||
761 | |||
762 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
763 | static void adv7842_inv_register(struct v4l2_subdev *sd) | ||
764 | { | ||
765 | v4l2_info(sd, "0x000-0x0ff: IO Map\n"); | ||
766 | v4l2_info(sd, "0x100-0x1ff: AVLink Map\n"); | ||
767 | v4l2_info(sd, "0x200-0x2ff: CEC Map\n"); | ||
768 | v4l2_info(sd, "0x300-0x3ff: InfoFrame Map\n"); | ||
769 | v4l2_info(sd, "0x400-0x4ff: SDP_IO Map\n"); | ||
770 | v4l2_info(sd, "0x500-0x5ff: SDP Map\n"); | ||
771 | v4l2_info(sd, "0x600-0x6ff: AFE Map\n"); | ||
772 | v4l2_info(sd, "0x700-0x7ff: Repeater Map\n"); | ||
773 | v4l2_info(sd, "0x800-0x8ff: EDID Map\n"); | ||
774 | v4l2_info(sd, "0x900-0x9ff: HDMI Map\n"); | ||
775 | v4l2_info(sd, "0xa00-0xaff: CP Map\n"); | ||
776 | v4l2_info(sd, "0xb00-0xbff: VDP Map\n"); | ||
777 | } | ||
778 | |||
779 | static int adv7842_g_register(struct v4l2_subdev *sd, | ||
780 | struct v4l2_dbg_register *reg) | ||
781 | { | ||
782 | reg->size = 1; | ||
783 | switch (reg->reg >> 8) { | ||
784 | case 0: | ||
785 | reg->val = io_read(sd, reg->reg & 0xff); | ||
786 | break; | ||
787 | case 1: | ||
788 | reg->val = avlink_read(sd, reg->reg & 0xff); | ||
789 | break; | ||
790 | case 2: | ||
791 | reg->val = cec_read(sd, reg->reg & 0xff); | ||
792 | break; | ||
793 | case 3: | ||
794 | reg->val = infoframe_read(sd, reg->reg & 0xff); | ||
795 | break; | ||
796 | case 4: | ||
797 | reg->val = sdp_io_read(sd, reg->reg & 0xff); | ||
798 | break; | ||
799 | case 5: | ||
800 | reg->val = sdp_read(sd, reg->reg & 0xff); | ||
801 | break; | ||
802 | case 6: | ||
803 | reg->val = afe_read(sd, reg->reg & 0xff); | ||
804 | break; | ||
805 | case 7: | ||
806 | reg->val = rep_read(sd, reg->reg & 0xff); | ||
807 | break; | ||
808 | case 8: | ||
809 | reg->val = edid_read(sd, reg->reg & 0xff); | ||
810 | break; | ||
811 | case 9: | ||
812 | reg->val = hdmi_read(sd, reg->reg & 0xff); | ||
813 | break; | ||
814 | case 0xa: | ||
815 | reg->val = cp_read(sd, reg->reg & 0xff); | ||
816 | break; | ||
817 | case 0xb: | ||
818 | reg->val = vdp_read(sd, reg->reg & 0xff); | ||
819 | break; | ||
820 | default: | ||
821 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | ||
822 | adv7842_inv_register(sd); | ||
823 | break; | ||
824 | } | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | static int adv7842_s_register(struct v4l2_subdev *sd, | ||
829 | const struct v4l2_dbg_register *reg) | ||
830 | { | ||
831 | u8 val = reg->val & 0xff; | ||
832 | |||
833 | switch (reg->reg >> 8) { | ||
834 | case 0: | ||
835 | io_write(sd, reg->reg & 0xff, val); | ||
836 | break; | ||
837 | case 1: | ||
838 | avlink_write(sd, reg->reg & 0xff, val); | ||
839 | break; | ||
840 | case 2: | ||
841 | cec_write(sd, reg->reg & 0xff, val); | ||
842 | break; | ||
843 | case 3: | ||
844 | infoframe_write(sd, reg->reg & 0xff, val); | ||
845 | break; | ||
846 | case 4: | ||
847 | sdp_io_write(sd, reg->reg & 0xff, val); | ||
848 | break; | ||
849 | case 5: | ||
850 | sdp_write(sd, reg->reg & 0xff, val); | ||
851 | break; | ||
852 | case 6: | ||
853 | afe_write(sd, reg->reg & 0xff, val); | ||
854 | break; | ||
855 | case 7: | ||
856 | rep_write(sd, reg->reg & 0xff, val); | ||
857 | break; | ||
858 | case 8: | ||
859 | edid_write(sd, reg->reg & 0xff, val); | ||
860 | break; | ||
861 | case 9: | ||
862 | hdmi_write(sd, reg->reg & 0xff, val); | ||
863 | break; | ||
864 | case 0xa: | ||
865 | cp_write(sd, reg->reg & 0xff, val); | ||
866 | break; | ||
867 | case 0xb: | ||
868 | vdp_write(sd, reg->reg & 0xff, val); | ||
869 | break; | ||
870 | default: | ||
871 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | ||
872 | adv7842_inv_register(sd); | ||
873 | break; | ||
874 | } | ||
875 | return 0; | ||
876 | } | ||
877 | #endif | ||
878 | |||
879 | static int adv7842_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) | ||
880 | { | ||
881 | struct adv7842_state *state = to_state(sd); | ||
882 | int prev = v4l2_ctrl_g_ctrl(state->detect_tx_5v_ctrl); | ||
883 | u8 reg_io_6f = io_read(sd, 0x6f); | ||
884 | int val = 0; | ||
885 | |||
886 | if (reg_io_6f & 0x02) | ||
887 | val |= 1; /* port A */ | ||
888 | if (reg_io_6f & 0x01) | ||
889 | val |= 2; /* port B */ | ||
890 | |||
891 | v4l2_dbg(1, debug, sd, "%s: 0x%x -> 0x%x\n", __func__, prev, val); | ||
892 | |||
893 | if (val != prev) | ||
894 | return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, val); | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, | ||
899 | u8 prim_mode, | ||
900 | const struct adv7842_video_standards *predef_vid_timings, | ||
901 | const struct v4l2_dv_timings *timings) | ||
902 | { | ||
903 | int i; | ||
904 | |||
905 | for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { | ||
906 | if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings, | ||
907 | is_digital_input(sd) ? 250000 : 1000000)) | ||
908 | continue; | ||
909 | /* video std */ | ||
910 | io_write(sd, 0x00, predef_vid_timings[i].vid_std); | ||
911 | /* v_freq and prim mode */ | ||
912 | io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) + prim_mode); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | return -1; | ||
917 | } | ||
918 | |||
919 | static int configure_predefined_video_timings(struct v4l2_subdev *sd, | ||
920 | struct v4l2_dv_timings *timings) | ||
921 | { | ||
922 | struct adv7842_state *state = to_state(sd); | ||
923 | int err; | ||
924 | |||
925 | v4l2_dbg(1, debug, sd, "%s\n", __func__); | ||
926 | |||
927 | /* reset to default values */ | ||
928 | io_write(sd, 0x16, 0x43); | ||
929 | io_write(sd, 0x17, 0x5a); | ||
930 | /* disable embedded syncs for auto graphics mode */ | ||
931 | cp_write_and_or(sd, 0x81, 0xef, 0x00); | ||
932 | cp_write(sd, 0x26, 0x00); | ||
933 | cp_write(sd, 0x27, 0x00); | ||
934 | cp_write(sd, 0x28, 0x00); | ||
935 | cp_write(sd, 0x29, 0x00); | ||
936 | cp_write(sd, 0x8f, 0x00); | ||
937 | cp_write(sd, 0x90, 0x00); | ||
938 | cp_write(sd, 0xa5, 0x00); | ||
939 | cp_write(sd, 0xa6, 0x00); | ||
940 | cp_write(sd, 0xa7, 0x00); | ||
941 | cp_write(sd, 0xab, 0x00); | ||
942 | cp_write(sd, 0xac, 0x00); | ||
943 | |||
944 | switch (state->mode) { | ||
945 | case ADV7842_MODE_COMP: | ||
946 | case ADV7842_MODE_RGB: | ||
947 | err = find_and_set_predefined_video_timings(sd, | ||
948 | 0x01, adv7842_prim_mode_comp, timings); | ||
949 | if (err) | ||
950 | err = find_and_set_predefined_video_timings(sd, | ||
951 | 0x02, adv7842_prim_mode_gr, timings); | ||
952 | break; | ||
953 | case ADV7842_MODE_HDMI: | ||
954 | err = find_and_set_predefined_video_timings(sd, | ||
955 | 0x05, adv7842_prim_mode_hdmi_comp, timings); | ||
956 | if (err) | ||
957 | err = find_and_set_predefined_video_timings(sd, | ||
958 | 0x06, adv7842_prim_mode_hdmi_gr, timings); | ||
959 | break; | ||
960 | default: | ||
961 | v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", | ||
962 | __func__, state->mode); | ||
963 | err = -1; | ||
964 | break; | ||
965 | } | ||
966 | |||
967 | |||
968 | return err; | ||
969 | } | ||
970 | |||
971 | static void configure_custom_video_timings(struct v4l2_subdev *sd, | ||
972 | const struct v4l2_bt_timings *bt) | ||
973 | { | ||
974 | struct adv7842_state *state = to_state(sd); | ||
975 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
976 | u32 width = htotal(bt); | ||
977 | u32 height = vtotal(bt); | ||
978 | u16 cp_start_sav = bt->hsync + bt->hbackporch - 4; | ||
979 | u16 cp_start_eav = width - bt->hfrontporch; | ||
980 | u16 cp_start_vbi = height - bt->vfrontporch + 1; | ||
981 | u16 cp_end_vbi = bt->vsync + bt->vbackporch + 1; | ||
982 | u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ? | ||
983 | ((width * (ADV7842_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0; | ||
984 | const u8 pll[2] = { | ||
985 | 0xc0 | ((width >> 8) & 0x1f), | ||
986 | width & 0xff | ||
987 | }; | ||
988 | |||
989 | v4l2_dbg(2, debug, sd, "%s\n", __func__); | ||
990 | |||
991 | switch (state->mode) { | ||
992 | case ADV7842_MODE_COMP: | ||
993 | case ADV7842_MODE_RGB: | ||
994 | /* auto graphics */ | ||
995 | io_write(sd, 0x00, 0x07); /* video std */ | ||
996 | io_write(sd, 0x01, 0x02); /* prim mode */ | ||
997 | /* enable embedded syncs for auto graphics mode */ | ||
998 | cp_write_and_or(sd, 0x81, 0xef, 0x10); | ||
999 | |||
1000 | /* Should only be set in auto-graphics mode [REF_02, p. 91-92] */ | ||
1001 | /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */ | ||
1002 | /* IO-map reg. 0x16 and 0x17 should be written in sequence */ | ||
1003 | if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) { | ||
1004 | v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n"); | ||
1005 | break; | ||
1006 | } | ||
1007 | |||
1008 | /* active video - horizontal timing */ | ||
1009 | cp_write(sd, 0x26, (cp_start_sav >> 8) & 0xf); | ||
1010 | cp_write(sd, 0x27, (cp_start_sav & 0xff)); | ||
1011 | cp_write(sd, 0x28, (cp_start_eav >> 8) & 0xf); | ||
1012 | cp_write(sd, 0x29, (cp_start_eav & 0xff)); | ||
1013 | |||
1014 | /* active video - vertical timing */ | ||
1015 | cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff); | ||
1016 | cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | | ||
1017 | ((cp_end_vbi >> 8) & 0xf)); | ||
1018 | cp_write(sd, 0xa7, cp_end_vbi & 0xff); | ||
1019 | break; | ||
1020 | case ADV7842_MODE_HDMI: | ||
1021 | /* set default prim_mode/vid_std for HDMI | ||
1022 | accoring to [REF_03, c. 4.2] */ | ||
1023 | io_write(sd, 0x00, 0x02); /* video std */ | ||
1024 | io_write(sd, 0x01, 0x06); /* prim mode */ | ||
1025 | break; | ||
1026 | default: | ||
1027 | v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", | ||
1028 | __func__, state->mode); | ||
1029 | break; | ||
1030 | } | ||
1031 | |||
1032 | cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7); | ||
1033 | cp_write(sd, 0x90, ch1_fr_ll & 0xff); | ||
1034 | cp_write(sd, 0xab, (height >> 4) & 0xff); | ||
1035 | cp_write(sd, 0xac, (height & 0x0f) << 4); | ||
1036 | } | ||
1037 | |||
1038 | static void set_rgb_quantization_range(struct v4l2_subdev *sd) | ||
1039 | { | ||
1040 | struct adv7842_state *state = to_state(sd); | ||
1041 | |||
1042 | switch (state->rgb_quantization_range) { | ||
1043 | case V4L2_DV_RGB_RANGE_AUTO: | ||
1044 | /* automatic */ | ||
1045 | if (is_digital_input(sd) && !(hdmi_read(sd, 0x05) & 0x80)) { | ||
1046 | /* receiving DVI-D signal */ | ||
1047 | |||
1048 | /* ADV7842 selects RGB limited range regardless of | ||
1049 | input format (CE/IT) in automatic mode */ | ||
1050 | if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) { | ||
1051 | /* RGB limited range (16-235) */ | ||
1052 | io_write_and_or(sd, 0x02, 0x0f, 0x00); | ||
1053 | |||
1054 | } else { | ||
1055 | /* RGB full range (0-255) */ | ||
1056 | io_write_and_or(sd, 0x02, 0x0f, 0x10); | ||
1057 | } | ||
1058 | } else { | ||
1059 | /* receiving HDMI or analog signal, set automode */ | ||
1060 | io_write_and_or(sd, 0x02, 0x0f, 0xf0); | ||
1061 | } | ||
1062 | break; | ||
1063 | case V4L2_DV_RGB_RANGE_LIMITED: | ||
1064 | /* RGB limited range (16-235) */ | ||
1065 | io_write_and_or(sd, 0x02, 0x0f, 0x00); | ||
1066 | break; | ||
1067 | case V4L2_DV_RGB_RANGE_FULL: | ||
1068 | /* RGB full range (0-255) */ | ||
1069 | io_write_and_or(sd, 0x02, 0x0f, 0x10); | ||
1070 | break; | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | static int adv7842_s_ctrl(struct v4l2_ctrl *ctrl) | ||
1075 | { | ||
1076 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
1077 | struct adv7842_state *state = to_state(sd); | ||
1078 | |||
1079 | /* TODO SDP ctrls | ||
1080 | contrast/brightness/hue/free run is acting a bit strange, | ||
1081 | not sure if sdp csc is correct. | ||
1082 | */ | ||
1083 | switch (ctrl->id) { | ||
1084 | /* standard ctrls */ | ||
1085 | case V4L2_CID_BRIGHTNESS: | ||
1086 | cp_write(sd, 0x3c, ctrl->val); | ||
1087 | sdp_write(sd, 0x14, ctrl->val); | ||
1088 | /* ignore lsb sdp 0x17[3:2] */ | ||
1089 | return 0; | ||
1090 | case V4L2_CID_CONTRAST: | ||
1091 | cp_write(sd, 0x3a, ctrl->val); | ||
1092 | sdp_write(sd, 0x13, ctrl->val); | ||
1093 | /* ignore lsb sdp 0x17[1:0] */ | ||
1094 | return 0; | ||
1095 | case V4L2_CID_SATURATION: | ||
1096 | cp_write(sd, 0x3b, ctrl->val); | ||
1097 | sdp_write(sd, 0x15, ctrl->val); | ||
1098 | /* ignore lsb sdp 0x17[5:4] */ | ||
1099 | return 0; | ||
1100 | case V4L2_CID_HUE: | ||
1101 | cp_write(sd, 0x3d, ctrl->val); | ||
1102 | sdp_write(sd, 0x16, ctrl->val); | ||
1103 | /* ignore lsb sdp 0x17[7:6] */ | ||
1104 | return 0; | ||
1105 | /* custom ctrls */ | ||
1106 | case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE: | ||
1107 | afe_write(sd, 0xc8, ctrl->val); | ||
1108 | return 0; | ||
1109 | case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL: | ||
1110 | cp_write_and_or(sd, 0xbf, ~0x04, (ctrl->val << 2)); | ||
1111 | sdp_write_and_or(sd, 0xdd, ~0x04, (ctrl->val << 2)); | ||
1112 | return 0; | ||
1113 | case V4L2_CID_ADV_RX_FREE_RUN_COLOR: { | ||
1114 | u8 R = (ctrl->val & 0xff0000) >> 16; | ||
1115 | u8 G = (ctrl->val & 0x00ff00) >> 8; | ||
1116 | u8 B = (ctrl->val & 0x0000ff); | ||
1117 | /* RGB -> YUV, numerical approximation */ | ||
1118 | int Y = 66 * R + 129 * G + 25 * B; | ||
1119 | int U = -38 * R - 74 * G + 112 * B; | ||
1120 | int V = 112 * R - 94 * G - 18 * B; | ||
1121 | |||
1122 | /* Scale down to 8 bits with rounding */ | ||
1123 | Y = (Y + 128) >> 8; | ||
1124 | U = (U + 128) >> 8; | ||
1125 | V = (V + 128) >> 8; | ||
1126 | /* make U,V positive */ | ||
1127 | Y += 16; | ||
1128 | U += 128; | ||
1129 | V += 128; | ||
1130 | |||
1131 | v4l2_dbg(1, debug, sd, "R %x, G %x, B %x\n", R, G, B); | ||
1132 | v4l2_dbg(1, debug, sd, "Y %x, U %x, V %x\n", Y, U, V); | ||
1133 | |||
1134 | /* CP */ | ||
1135 | cp_write(sd, 0xc1, R); | ||
1136 | cp_write(sd, 0xc0, G); | ||
1137 | cp_write(sd, 0xc2, B); | ||
1138 | /* SDP */ | ||
1139 | sdp_write(sd, 0xde, Y); | ||
1140 | sdp_write(sd, 0xdf, (V & 0xf0) | ((U >> 4) & 0x0f)); | ||
1141 | return 0; | ||
1142 | } | ||
1143 | case V4L2_CID_DV_RX_RGB_RANGE: | ||
1144 | state->rgb_quantization_range = ctrl->val; | ||
1145 | set_rgb_quantization_range(sd); | ||
1146 | return 0; | ||
1147 | } | ||
1148 | return -EINVAL; | ||
1149 | } | ||
1150 | |||
1151 | static inline bool no_power(struct v4l2_subdev *sd) | ||
1152 | { | ||
1153 | return io_read(sd, 0x0c) & 0x24; | ||
1154 | } | ||
1155 | |||
1156 | static inline bool no_cp_signal(struct v4l2_subdev *sd) | ||
1157 | { | ||
1158 | return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0) || !(cp_read(sd, 0xb1) & 0x80); | ||
1159 | } | ||
1160 | |||
1161 | static inline bool is_hdmi(struct v4l2_subdev *sd) | ||
1162 | { | ||
1163 | return hdmi_read(sd, 0x05) & 0x80; | ||
1164 | } | ||
1165 | |||
1166 | static int adv7842_g_input_status(struct v4l2_subdev *sd, u32 *status) | ||
1167 | { | ||
1168 | struct adv7842_state *state = to_state(sd); | ||
1169 | |||
1170 | *status = 0; | ||
1171 | |||
1172 | if (io_read(sd, 0x0c) & 0x24) | ||
1173 | *status |= V4L2_IN_ST_NO_POWER; | ||
1174 | |||
1175 | if (state->mode == ADV7842_MODE_SDP) { | ||
1176 | /* status from SDP block */ | ||
1177 | if (!(sdp_read(sd, 0x5A) & 0x01)) | ||
1178 | *status |= V4L2_IN_ST_NO_SIGNAL; | ||
1179 | |||
1180 | v4l2_dbg(1, debug, sd, "%s: SDP status = 0x%x\n", | ||
1181 | __func__, *status); | ||
1182 | return 0; | ||
1183 | } | ||
1184 | /* status from CP block */ | ||
1185 | if ((cp_read(sd, 0xb5) & 0xd0) != 0xd0 || | ||
1186 | !(cp_read(sd, 0xb1) & 0x80)) | ||
1187 | /* TODO channel 2 */ | ||
1188 | *status |= V4L2_IN_ST_NO_SIGNAL; | ||
1189 | |||
1190 | if (is_digital_input(sd) && ((io_read(sd, 0x74) & 0x03) != 0x03)) | ||
1191 | *status |= V4L2_IN_ST_NO_SIGNAL; | ||
1192 | |||
1193 | v4l2_dbg(1, debug, sd, "%s: CP status = 0x%x\n", | ||
1194 | __func__, *status); | ||
1195 | |||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1199 | struct stdi_readback { | ||
1200 | u16 bl, lcf, lcvs; | ||
1201 | u8 hs_pol, vs_pol; | ||
1202 | bool interlaced; | ||
1203 | }; | ||
1204 | |||
1205 | static int stdi2dv_timings(struct v4l2_subdev *sd, | ||
1206 | struct stdi_readback *stdi, | ||
1207 | struct v4l2_dv_timings *timings) | ||
1208 | { | ||
1209 | struct adv7842_state *state = to_state(sd); | ||
1210 | u32 hfreq = (ADV7842_fsc * 8) / stdi->bl; | ||
1211 | u32 pix_clk; | ||
1212 | int i; | ||
1213 | |||
1214 | for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) { | ||
1215 | const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt; | ||
1216 | |||
1217 | if (!v4l2_valid_dv_timings(&v4l2_dv_timings_presets[i], | ||
1218 | adv7842_get_dv_timings_cap(sd), | ||
1219 | adv7842_check_dv_timings, NULL)) | ||
1220 | continue; | ||
1221 | if (vtotal(bt) != stdi->lcf + 1) | ||
1222 | continue; | ||
1223 | if (bt->vsync != stdi->lcvs) | ||
1224 | continue; | ||
1225 | |||
1226 | pix_clk = hfreq * htotal(bt); | ||
1227 | |||
1228 | if ((pix_clk < bt->pixelclock + 1000000) && | ||
1229 | (pix_clk > bt->pixelclock - 1000000)) { | ||
1230 | *timings = v4l2_dv_timings_presets[i]; | ||
1231 | return 0; | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1235 | if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, | ||
1236 | (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | | ||
1237 | (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), | ||
1238 | timings)) | ||
1239 | return 0; | ||
1240 | if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs, | ||
1241 | (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | | ||
1242 | (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), | ||
1243 | state->aspect_ratio, timings)) | ||
1244 | return 0; | ||
1245 | |||
1246 | v4l2_dbg(2, debug, sd, | ||
1247 | "%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n", | ||
1248 | __func__, stdi->lcvs, stdi->lcf, stdi->bl, | ||
1249 | stdi->hs_pol, stdi->vs_pol); | ||
1250 | return -1; | ||
1251 | } | ||
1252 | |||
1253 | static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi) | ||
1254 | { | ||
1255 | u32 status; | ||
1256 | |||
1257 | adv7842_g_input_status(sd, &status); | ||
1258 | if (status & V4L2_IN_ST_NO_SIGNAL) { | ||
1259 | v4l2_dbg(2, debug, sd, "%s: no signal\n", __func__); | ||
1260 | return -ENOLINK; | ||
1261 | } | ||
1262 | |||
1263 | stdi->bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2); | ||
1264 | stdi->lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4); | ||
1265 | stdi->lcvs = cp_read(sd, 0xb3) >> 3; | ||
1266 | |||
1267 | if ((cp_read(sd, 0xb5) & 0x80) && ((cp_read(sd, 0xb5) & 0x03) == 0x01)) { | ||
1268 | stdi->hs_pol = ((cp_read(sd, 0xb5) & 0x10) ? | ||
1269 | ((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x'); | ||
1270 | stdi->vs_pol = ((cp_read(sd, 0xb5) & 0x40) ? | ||
1271 | ((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x'); | ||
1272 | } else { | ||
1273 | stdi->hs_pol = 'x'; | ||
1274 | stdi->vs_pol = 'x'; | ||
1275 | } | ||
1276 | stdi->interlaced = (cp_read(sd, 0xb1) & 0x40) ? true : false; | ||
1277 | |||
1278 | if (stdi->lcf < 239 || stdi->bl < 8 || stdi->bl == 0x3fff) { | ||
1279 | v4l2_dbg(2, debug, sd, "%s: invalid signal\n", __func__); | ||
1280 | return -ENOLINK; | ||
1281 | } | ||
1282 | |||
1283 | v4l2_dbg(2, debug, sd, | ||
1284 | "%s: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %chsync, %cvsync, %s\n", | ||
1285 | __func__, stdi->lcf, stdi->bl, stdi->lcvs, | ||
1286 | stdi->hs_pol, stdi->vs_pol, | ||
1287 | stdi->interlaced ? "interlaced" : "progressive"); | ||
1288 | |||
1289 | return 0; | ||
1290 | } | ||
1291 | |||
1292 | static int adv7842_enum_dv_timings(struct v4l2_subdev *sd, | ||
1293 | struct v4l2_enum_dv_timings *timings) | ||
1294 | { | ||
1295 | return v4l2_enum_dv_timings_cap(timings, | ||
1296 | adv7842_get_dv_timings_cap(sd), adv7842_check_dv_timings, NULL); | ||
1297 | } | ||
1298 | |||
1299 | static int adv7842_dv_timings_cap(struct v4l2_subdev *sd, | ||
1300 | struct v4l2_dv_timings_cap *cap) | ||
1301 | { | ||
1302 | *cap = *adv7842_get_dv_timings_cap(sd); | ||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings | ||
1307 | if the format is listed in adv7604_timings[] */ | ||
1308 | static void adv7842_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, | ||
1309 | struct v4l2_dv_timings *timings) | ||
1310 | { | ||
1311 | v4l2_find_dv_timings_cap(timings, adv7842_get_dv_timings_cap(sd), | ||
1312 | is_digital_input(sd) ? 250000 : 1000000, | ||
1313 | adv7842_check_dv_timings, NULL); | ||
1314 | } | ||
1315 | |||
1316 | static int adv7842_query_dv_timings(struct v4l2_subdev *sd, | ||
1317 | struct v4l2_dv_timings *timings) | ||
1318 | { | ||
1319 | struct adv7842_state *state = to_state(sd); | ||
1320 | struct v4l2_bt_timings *bt = &timings->bt; | ||
1321 | struct stdi_readback stdi = { 0 }; | ||
1322 | |||
1323 | /* SDP block */ | ||
1324 | if (state->mode == ADV7842_MODE_SDP) | ||
1325 | return -ENODATA; | ||
1326 | |||
1327 | /* read STDI */ | ||
1328 | if (read_stdi(sd, &stdi)) { | ||
1329 | v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__); | ||
1330 | return -ENOLINK; | ||
1331 | } | ||
1332 | bt->interlaced = stdi.interlaced ? | ||
1333 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; | ||
1334 | bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) | | ||
1335 | ((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0); | ||
1336 | bt->vsync = stdi.lcvs; | ||
1337 | |||
1338 | if (is_digital_input(sd)) { | ||
1339 | bool lock = hdmi_read(sd, 0x04) & 0x02; | ||
1340 | bool interlaced = hdmi_read(sd, 0x0b) & 0x20; | ||
1341 | unsigned w = (hdmi_read(sd, 0x07) & 0x1f) * 256 + hdmi_read(sd, 0x08); | ||
1342 | unsigned h = (hdmi_read(sd, 0x09) & 0x1f) * 256 + hdmi_read(sd, 0x0a); | ||
1343 | unsigned w_total = (hdmi_read(sd, 0x1e) & 0x3f) * 256 + | ||
1344 | hdmi_read(sd, 0x1f); | ||
1345 | unsigned h_total = ((hdmi_read(sd, 0x26) & 0x3f) * 256 + | ||
1346 | hdmi_read(sd, 0x27)) / 2; | ||
1347 | unsigned freq = (((hdmi_read(sd, 0x51) << 1) + | ||
1348 | (hdmi_read(sd, 0x52) >> 7)) * 1000000) + | ||
1349 | ((hdmi_read(sd, 0x52) & 0x7f) * 1000000) / 128; | ||
1350 | int i; | ||
1351 | |||
1352 | if (is_hdmi(sd)) { | ||
1353 | /* adjust for deep color mode */ | ||
1354 | freq = freq * 8 / (((hdmi_read(sd, 0x0b) & 0xc0)>>6) * 2 + 8); | ||
1355 | } | ||
1356 | |||
1357 | /* No lock? */ | ||
1358 | if (!lock) { | ||
1359 | v4l2_dbg(1, debug, sd, "%s: no lock on TMDS signal\n", __func__); | ||
1360 | return -ENOLCK; | ||
1361 | } | ||
1362 | /* Interlaced? */ | ||
1363 | if (interlaced) { | ||
1364 | v4l2_dbg(1, debug, sd, "%s: interlaced video not supported\n", __func__); | ||
1365 | return -ERANGE; | ||
1366 | } | ||
1367 | |||
1368 | for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) { | ||
1369 | const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt; | ||
1370 | |||
1371 | if (!v4l2_valid_dv_timings(&v4l2_dv_timings_presets[i], | ||
1372 | adv7842_get_dv_timings_cap(sd), | ||
1373 | adv7842_check_dv_timings, NULL)) | ||
1374 | continue; | ||
1375 | if (w_total != htotal(bt) || h_total != vtotal(bt)) | ||
1376 | continue; | ||
1377 | |||
1378 | if (w != bt->width || h != bt->height) | ||
1379 | continue; | ||
1380 | |||
1381 | if (abs(freq - bt->pixelclock) > 1000000) | ||
1382 | continue; | ||
1383 | *timings = v4l2_dv_timings_presets[i]; | ||
1384 | return 0; | ||
1385 | } | ||
1386 | |||
1387 | timings->type = V4L2_DV_BT_656_1120; | ||
1388 | |||
1389 | bt->width = w; | ||
1390 | bt->height = h; | ||
1391 | bt->interlaced = (hdmi_read(sd, 0x0b) & 0x20) ? | ||
1392 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; | ||
1393 | bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? | ||
1394 | V4L2_DV_VSYNC_POS_POL : 0) | ((hdmi_read(sd, 0x05) & 0x20) ? | ||
1395 | V4L2_DV_HSYNC_POS_POL : 0); | ||
1396 | bt->pixelclock = (((hdmi_read(sd, 0x51) << 1) + | ||
1397 | (hdmi_read(sd, 0x52) >> 7)) * 1000000) + | ||
1398 | ((hdmi_read(sd, 0x52) & 0x7f) * 1000000) / 128; | ||
1399 | bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x1f) * 256 + | ||
1400 | hdmi_read(sd, 0x21); | ||
1401 | bt->hsync = (hdmi_read(sd, 0x22) & 0x1f) * 256 + | ||
1402 | hdmi_read(sd, 0x23); | ||
1403 | bt->hbackporch = (hdmi_read(sd, 0x24) & 0x1f) * 256 + | ||
1404 | hdmi_read(sd, 0x25); | ||
1405 | bt->vfrontporch = ((hdmi_read(sd, 0x2a) & 0x3f) * 256 + | ||
1406 | hdmi_read(sd, 0x2b)) / 2; | ||
1407 | bt->il_vfrontporch = ((hdmi_read(sd, 0x2c) & 0x3f) * 256 + | ||
1408 | hdmi_read(sd, 0x2d)) / 2; | ||
1409 | bt->vsync = ((hdmi_read(sd, 0x2e) & 0x3f) * 256 + | ||
1410 | hdmi_read(sd, 0x2f)) / 2; | ||
1411 | bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x3f) * 256 + | ||
1412 | hdmi_read(sd, 0x31)) / 2; | ||
1413 | bt->vbackporch = ((hdmi_read(sd, 0x32) & 0x3f) * 256 + | ||
1414 | hdmi_read(sd, 0x33)) / 2; | ||
1415 | bt->il_vbackporch = ((hdmi_read(sd, 0x34) & 0x3f) * 256 + | ||
1416 | hdmi_read(sd, 0x35)) / 2; | ||
1417 | |||
1418 | bt->standards = 0; | ||
1419 | bt->flags = 0; | ||
1420 | } else { | ||
1421 | /* Interlaced? */ | ||
1422 | if (stdi.interlaced) { | ||
1423 | v4l2_dbg(1, debug, sd, "%s: interlaced video not supported\n", __func__); | ||
1424 | return -ERANGE; | ||
1425 | } | ||
1426 | |||
1427 | if (stdi2dv_timings(sd, &stdi, timings)) { | ||
1428 | v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__); | ||
1429 | return -ERANGE; | ||
1430 | } | ||
1431 | } | ||
1432 | |||
1433 | if (debug > 1) | ||
1434 | v4l2_print_dv_timings(sd->name, "adv7842_query_dv_timings: ", | ||
1435 | timings, true); | ||
1436 | return 0; | ||
1437 | } | ||
1438 | |||
1439 | static int adv7842_s_dv_timings(struct v4l2_subdev *sd, | ||
1440 | struct v4l2_dv_timings *timings) | ||
1441 | { | ||
1442 | struct adv7842_state *state = to_state(sd); | ||
1443 | struct v4l2_bt_timings *bt; | ||
1444 | int err; | ||
1445 | |||
1446 | if (state->mode == ADV7842_MODE_SDP) | ||
1447 | return -ENODATA; | ||
1448 | |||
1449 | bt = &timings->bt; | ||
1450 | |||
1451 | if (!v4l2_valid_dv_timings(timings, adv7842_get_dv_timings_cap(sd), | ||
1452 | adv7842_check_dv_timings, NULL)) | ||
1453 | return -ERANGE; | ||
1454 | |||
1455 | adv7842_fill_optional_dv_timings_fields(sd, timings); | ||
1456 | |||
1457 | state->timings = *timings; | ||
1458 | |||
1459 | cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10); | ||
1460 | |||
1461 | /* Use prim_mode and vid_std when available */ | ||
1462 | err = configure_predefined_video_timings(sd, timings); | ||
1463 | if (err) { | ||
1464 | /* custom settings when the video format | ||
1465 | does not have prim_mode/vid_std */ | ||
1466 | configure_custom_video_timings(sd, bt); | ||
1467 | } | ||
1468 | |||
1469 | set_rgb_quantization_range(sd); | ||
1470 | |||
1471 | |||
1472 | if (debug > 1) | ||
1473 | v4l2_print_dv_timings(sd->name, "adv7842_s_dv_timings: ", | ||
1474 | timings, true); | ||
1475 | return 0; | ||
1476 | } | ||
1477 | |||
1478 | static int adv7842_g_dv_timings(struct v4l2_subdev *sd, | ||
1479 | struct v4l2_dv_timings *timings) | ||
1480 | { | ||
1481 | struct adv7842_state *state = to_state(sd); | ||
1482 | |||
1483 | if (state->mode == ADV7842_MODE_SDP) | ||
1484 | return -ENODATA; | ||
1485 | *timings = state->timings; | ||
1486 | return 0; | ||
1487 | } | ||
1488 | |||
1489 | static void enable_input(struct v4l2_subdev *sd) | ||
1490 | { | ||
1491 | struct adv7842_state *state = to_state(sd); | ||
1492 | switch (state->mode) { | ||
1493 | case ADV7842_MODE_SDP: | ||
1494 | case ADV7842_MODE_COMP: | ||
1495 | case ADV7842_MODE_RGB: | ||
1496 | /* enable */ | ||
1497 | io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */ | ||
1498 | break; | ||
1499 | case ADV7842_MODE_HDMI: | ||
1500 | /* enable */ | ||
1501 | hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */ | ||
1502 | hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */ | ||
1503 | io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */ | ||
1504 | break; | ||
1505 | default: | ||
1506 | v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", | ||
1507 | __func__, state->mode); | ||
1508 | break; | ||
1509 | } | ||
1510 | } | ||
1511 | |||
1512 | static void disable_input(struct v4l2_subdev *sd) | ||
1513 | { | ||
1514 | /* disable */ | ||
1515 | io_write(sd, 0x15, 0xbe); /* Tristate all outputs from video core */ | ||
1516 | hdmi_write(sd, 0x1a, 0x1a); /* Mute audio */ | ||
1517 | hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */ | ||
1518 | } | ||
1519 | |||
1520 | static void sdp_csc_coeff(struct v4l2_subdev *sd, | ||
1521 | const struct adv7842_sdp_csc_coeff *c) | ||
1522 | { | ||
1523 | /* csc auto/manual */ | ||
1524 | sdp_io_write_and_or(sd, 0xe0, 0xbf, c->manual ? 0x00 : 0x40); | ||
1525 | |||
1526 | if (!c->manual) | ||
1527 | return; | ||
1528 | |||
1529 | /* csc scaling */ | ||
1530 | sdp_io_write_and_or(sd, 0xe0, 0x7f, c->scaling == 2 ? 0x80 : 0x00); | ||
1531 | |||
1532 | /* A coeff */ | ||
1533 | sdp_io_write_and_or(sd, 0xe0, 0xe0, c->A1 >> 8); | ||
1534 | sdp_io_write(sd, 0xe1, c->A1); | ||
1535 | sdp_io_write_and_or(sd, 0xe2, 0xe0, c->A2 >> 8); | ||
1536 | sdp_io_write(sd, 0xe3, c->A2); | ||
1537 | sdp_io_write_and_or(sd, 0xe4, 0xe0, c->A3 >> 8); | ||
1538 | sdp_io_write(sd, 0xe5, c->A3); | ||
1539 | |||
1540 | /* A scale */ | ||
1541 | sdp_io_write_and_or(sd, 0xe6, 0x80, c->A4 >> 8); | ||
1542 | sdp_io_write(sd, 0xe7, c->A4); | ||
1543 | |||
1544 | /* B coeff */ | ||
1545 | sdp_io_write_and_or(sd, 0xe8, 0xe0, c->B1 >> 8); | ||
1546 | sdp_io_write(sd, 0xe9, c->B1); | ||
1547 | sdp_io_write_and_or(sd, 0xea, 0xe0, c->B2 >> 8); | ||
1548 | sdp_io_write(sd, 0xeb, c->B2); | ||
1549 | sdp_io_write_and_or(sd, 0xec, 0xe0, c->B3 >> 8); | ||
1550 | sdp_io_write(sd, 0xed, c->B3); | ||
1551 | |||
1552 | /* B scale */ | ||
1553 | sdp_io_write_and_or(sd, 0xee, 0x80, c->B4 >> 8); | ||
1554 | sdp_io_write(sd, 0xef, c->B4); | ||
1555 | |||
1556 | /* C coeff */ | ||
1557 | sdp_io_write_and_or(sd, 0xf0, 0xe0, c->C1 >> 8); | ||
1558 | sdp_io_write(sd, 0xf1, c->C1); | ||
1559 | sdp_io_write_and_or(sd, 0xf2, 0xe0, c->C2 >> 8); | ||
1560 | sdp_io_write(sd, 0xf3, c->C2); | ||
1561 | sdp_io_write_and_or(sd, 0xf4, 0xe0, c->C3 >> 8); | ||
1562 | sdp_io_write(sd, 0xf5, c->C3); | ||
1563 | |||
1564 | /* C scale */ | ||
1565 | sdp_io_write_and_or(sd, 0xf6, 0x80, c->C4 >> 8); | ||
1566 | sdp_io_write(sd, 0xf7, c->C4); | ||
1567 | } | ||
1568 | |||
1569 | static void select_input(struct v4l2_subdev *sd, | ||
1570 | enum adv7842_vid_std_select vid_std_select) | ||
1571 | { | ||
1572 | struct adv7842_state *state = to_state(sd); | ||
1573 | |||
1574 | switch (state->mode) { | ||
1575 | case ADV7842_MODE_SDP: | ||
1576 | io_write(sd, 0x00, vid_std_select); /* video std: CVBS or YC mode */ | ||
1577 | io_write(sd, 0x01, 0); /* prim mode */ | ||
1578 | /* enable embedded syncs for auto graphics mode */ | ||
1579 | cp_write_and_or(sd, 0x81, 0xef, 0x10); | ||
1580 | |||
1581 | afe_write(sd, 0x00, 0x00); /* power up ADC */ | ||
1582 | afe_write(sd, 0xc8, 0x00); /* phase control */ | ||
1583 | |||
1584 | io_write(sd, 0x19, 0x83); /* LLC DLL phase */ | ||
1585 | io_write(sd, 0x33, 0x40); /* LLC DLL enable */ | ||
1586 | |||
1587 | io_write(sd, 0xdd, 0x90); /* Manual 2x output clock */ | ||
1588 | /* script says register 0xde, which don't exist in manual */ | ||
1589 | |||
1590 | /* Manual analog input muxing mode, CVBS (6.4)*/ | ||
1591 | afe_write_and_or(sd, 0x02, 0x7f, 0x80); | ||
1592 | if (vid_std_select == ADV7842_SDP_VID_STD_CVBS_SD_4x1) { | ||
1593 | afe_write(sd, 0x03, 0xa0); /* ADC0 to AIN10 (CVBS), ADC1 N/C*/ | ||
1594 | afe_write(sd, 0x04, 0x00); /* ADC2 N/C,ADC3 N/C*/ | ||
1595 | } else { | ||
1596 | afe_write(sd, 0x03, 0xa0); /* ADC0 to AIN10 (CVBS), ADC1 N/C*/ | ||
1597 | afe_write(sd, 0x04, 0xc0); /* ADC2 to AIN12, ADC3 N/C*/ | ||
1598 | } | ||
1599 | afe_write(sd, 0x0c, 0x1f); /* ADI recommend write */ | ||
1600 | afe_write(sd, 0x12, 0x63); /* ADI recommend write */ | ||
1601 | |||
1602 | sdp_io_write(sd, 0xb2, 0x60); /* Disable AV codes */ | ||
1603 | sdp_io_write(sd, 0xc8, 0xe3); /* Disable Ancillary data */ | ||
1604 | |||
1605 | /* SDP recommended settings */ | ||
1606 | sdp_write(sd, 0x00, 0x3F); /* Autodetect PAL NTSC (not SECAM) */ | ||
1607 | sdp_write(sd, 0x01, 0x00); /* Pedestal Off */ | ||
1608 | |||
1609 | sdp_write(sd, 0x03, 0xE4); /* Manual VCR Gain Luma 0x40B */ | ||
1610 | sdp_write(sd, 0x04, 0x0B); /* Manual Luma setting */ | ||
1611 | sdp_write(sd, 0x05, 0xC3); /* Manual Chroma setting 0x3FE */ | ||
1612 | sdp_write(sd, 0x06, 0xFE); /* Manual Chroma setting */ | ||
1613 | sdp_write(sd, 0x12, 0x0D); /* Frame TBC,I_P, 3D comb enabled */ | ||
1614 | sdp_write(sd, 0xA7, 0x00); /* ADI Recommended Write */ | ||
1615 | sdp_io_write(sd, 0xB0, 0x00); /* Disable H and v blanking */ | ||
1616 | |||
1617 | /* deinterlacer enabled and 3D comb */ | ||
1618 | sdp_write_and_or(sd, 0x12, 0xf6, 0x09); | ||
1619 | |||
1620 | sdp_write(sd, 0xdd, 0x08); /* free run auto */ | ||
1621 | |||
1622 | break; | ||
1623 | |||
1624 | case ADV7842_MODE_COMP: | ||
1625 | case ADV7842_MODE_RGB: | ||
1626 | /* Automatic analog input muxing mode */ | ||
1627 | afe_write_and_or(sd, 0x02, 0x7f, 0x00); | ||
1628 | /* set mode and select free run resolution */ | ||
1629 | io_write(sd, 0x00, vid_std_select); /* video std */ | ||
1630 | io_write(sd, 0x01, 0x02); /* prim mode */ | ||
1631 | cp_write_and_or(sd, 0x81, 0xef, 0x10); /* enable embedded syncs | ||
1632 | for auto graphics mode */ | ||
1633 | |||
1634 | afe_write(sd, 0x00, 0x00); /* power up ADC */ | ||
1635 | afe_write(sd, 0xc8, 0x00); /* phase control */ | ||
1636 | |||
1637 | /* set ADI recommended settings for digitizer */ | ||
1638 | /* "ADV7842 Register Settings Recommendations | ||
1639 | * (rev. 1.8, November 2010)" p. 9. */ | ||
1640 | afe_write(sd, 0x0c, 0x1f); /* ADC Range improvement */ | ||
1641 | afe_write(sd, 0x12, 0x63); /* ADC Range improvement */ | ||
1642 | |||
1643 | /* set to default gain for RGB */ | ||
1644 | cp_write(sd, 0x73, 0x10); | ||
1645 | cp_write(sd, 0x74, 0x04); | ||
1646 | cp_write(sd, 0x75, 0x01); | ||
1647 | cp_write(sd, 0x76, 0x00); | ||
1648 | |||
1649 | cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */ | ||
1650 | cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */ | ||
1651 | cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */ | ||
1652 | break; | ||
1653 | |||
1654 | case ADV7842_MODE_HDMI: | ||
1655 | /* Automatic analog input muxing mode */ | ||
1656 | afe_write_and_or(sd, 0x02, 0x7f, 0x00); | ||
1657 | /* set mode and select free run resolution */ | ||
1658 | if (state->hdmi_port_a) | ||
1659 | hdmi_write(sd, 0x00, 0x02); /* select port A */ | ||
1660 | else | ||
1661 | hdmi_write(sd, 0x00, 0x03); /* select port B */ | ||
1662 | io_write(sd, 0x00, vid_std_select); /* video std */ | ||
1663 | io_write(sd, 0x01, 5); /* prim mode */ | ||
1664 | cp_write_and_or(sd, 0x81, 0xef, 0x00); /* disable embedded syncs | ||
1665 | for auto graphics mode */ | ||
1666 | |||
1667 | /* set ADI recommended settings for HDMI: */ | ||
1668 | /* "ADV7842 Register Settings Recommendations | ||
1669 | * (rev. 1.8, November 2010)" p. 3. */ | ||
1670 | hdmi_write(sd, 0xc0, 0x00); | ||
1671 | hdmi_write(sd, 0x0d, 0x34); /* ADI recommended write */ | ||
1672 | hdmi_write(sd, 0x3d, 0x10); /* ADI recommended write */ | ||
1673 | hdmi_write(sd, 0x44, 0x85); /* TMDS PLL optimization */ | ||
1674 | hdmi_write(sd, 0x46, 0x1f); /* ADI recommended write */ | ||
1675 | hdmi_write(sd, 0x57, 0xb6); /* TMDS PLL optimization */ | ||
1676 | hdmi_write(sd, 0x58, 0x03); /* TMDS PLL optimization */ | ||
1677 | hdmi_write(sd, 0x60, 0x88); /* TMDS PLL optimization */ | ||
1678 | hdmi_write(sd, 0x61, 0x88); /* TMDS PLL optimization */ | ||
1679 | hdmi_write(sd, 0x6c, 0x18); /* Disable ISRC clearing bit, | ||
1680 | Improve robustness */ | ||
1681 | hdmi_write(sd, 0x75, 0x10); /* DDC drive strength */ | ||
1682 | hdmi_write(sd, 0x85, 0x1f); /* equaliser */ | ||
1683 | hdmi_write(sd, 0x87, 0x70); /* ADI recommended write */ | ||
1684 | hdmi_write(sd, 0x89, 0x04); /* equaliser */ | ||
1685 | hdmi_write(sd, 0x8a, 0x1e); /* equaliser */ | ||
1686 | hdmi_write(sd, 0x93, 0x04); /* equaliser */ | ||
1687 | hdmi_write(sd, 0x94, 0x1e); /* equaliser */ | ||
1688 | hdmi_write(sd, 0x99, 0xa1); /* ADI recommended write */ | ||
1689 | hdmi_write(sd, 0x9b, 0x09); /* ADI recommended write */ | ||
1690 | hdmi_write(sd, 0x9d, 0x02); /* equaliser */ | ||
1691 | |||
1692 | afe_write(sd, 0x00, 0xff); /* power down ADC */ | ||
1693 | afe_write(sd, 0xc8, 0x40); /* phase control */ | ||
1694 | |||
1695 | /* set to default gain for HDMI */ | ||
1696 | cp_write(sd, 0x73, 0x10); | ||
1697 | cp_write(sd, 0x74, 0x04); | ||
1698 | cp_write(sd, 0x75, 0x01); | ||
1699 | cp_write(sd, 0x76, 0x00); | ||
1700 | |||
1701 | /* reset ADI recommended settings for digitizer */ | ||
1702 | /* "ADV7842 Register Settings Recommendations | ||
1703 | * (rev. 2.5, June 2010)" p. 17. */ | ||
1704 | afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */ | ||
1705 | afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */ | ||
1706 | cp_write(sd, 0x3e, 0x80); /* CP core pre-gain control, | ||
1707 | enable color control */ | ||
1708 | /* CP coast control */ | ||
1709 | cp_write(sd, 0xc3, 0x33); /* Component mode */ | ||
1710 | |||
1711 | /* color space conversion, autodetect color space */ | ||
1712 | io_write_and_or(sd, 0x02, 0x0f, 0xf0); | ||
1713 | break; | ||
1714 | |||
1715 | default: | ||
1716 | v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", | ||
1717 | __func__, state->mode); | ||
1718 | break; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | static int adv7842_s_routing(struct v4l2_subdev *sd, | ||
1723 | u32 input, u32 output, u32 config) | ||
1724 | { | ||
1725 | struct adv7842_state *state = to_state(sd); | ||
1726 | |||
1727 | v4l2_dbg(2, debug, sd, "%s: input %d\n", __func__, input); | ||
1728 | |||
1729 | switch (input) { | ||
1730 | case ADV7842_SELECT_HDMI_PORT_A: | ||
1731 | /* TODO select HDMI_COMP or HDMI_GR */ | ||
1732 | state->mode = ADV7842_MODE_HDMI; | ||
1733 | state->vid_std_select = ADV7842_HDMI_COMP_VID_STD_HD_1250P; | ||
1734 | state->hdmi_port_a = true; | ||
1735 | break; | ||
1736 | case ADV7842_SELECT_HDMI_PORT_B: | ||
1737 | /* TODO select HDMI_COMP or HDMI_GR */ | ||
1738 | state->mode = ADV7842_MODE_HDMI; | ||
1739 | state->vid_std_select = ADV7842_HDMI_COMP_VID_STD_HD_1250P; | ||
1740 | state->hdmi_port_a = false; | ||
1741 | break; | ||
1742 | case ADV7842_SELECT_VGA_COMP: | ||
1743 | v4l2_info(sd, "%s: VGA component: todo\n", __func__); | ||
1744 | case ADV7842_SELECT_VGA_RGB: | ||
1745 | state->mode = ADV7842_MODE_RGB; | ||
1746 | state->vid_std_select = ADV7842_RGB_VID_STD_AUTO_GRAPH_MODE; | ||
1747 | break; | ||
1748 | case ADV7842_SELECT_SDP_CVBS: | ||
1749 | state->mode = ADV7842_MODE_SDP; | ||
1750 | state->vid_std_select = ADV7842_SDP_VID_STD_CVBS_SD_4x1; | ||
1751 | break; | ||
1752 | case ADV7842_SELECT_SDP_YC: | ||
1753 | state->mode = ADV7842_MODE_SDP; | ||
1754 | state->vid_std_select = ADV7842_SDP_VID_STD_YC_SD4_x1; | ||
1755 | break; | ||
1756 | default: | ||
1757 | return -EINVAL; | ||
1758 | } | ||
1759 | |||
1760 | disable_input(sd); | ||
1761 | select_input(sd, state->vid_std_select); | ||
1762 | enable_input(sd); | ||
1763 | |||
1764 | v4l2_subdev_notify(sd, ADV7842_FMT_CHANGE, NULL); | ||
1765 | |||
1766 | return 0; | ||
1767 | } | ||
1768 | |||
1769 | static int adv7842_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, | ||
1770 | enum v4l2_mbus_pixelcode *code) | ||
1771 | { | ||
1772 | if (index) | ||
1773 | return -EINVAL; | ||
1774 | /* Good enough for now */ | ||
1775 | *code = V4L2_MBUS_FMT_FIXED; | ||
1776 | return 0; | ||
1777 | } | ||
1778 | |||
1779 | static int adv7842_g_mbus_fmt(struct v4l2_subdev *sd, | ||
1780 | struct v4l2_mbus_framefmt *fmt) | ||
1781 | { | ||
1782 | struct adv7842_state *state = to_state(sd); | ||
1783 | |||
1784 | fmt->width = state->timings.bt.width; | ||
1785 | fmt->height = state->timings.bt.height; | ||
1786 | fmt->code = V4L2_MBUS_FMT_FIXED; | ||
1787 | fmt->field = V4L2_FIELD_NONE; | ||
1788 | |||
1789 | if (state->mode == ADV7842_MODE_SDP) { | ||
1790 | /* SPD block */ | ||
1791 | if (!(sdp_read(sd, 0x5A) & 0x01)) | ||
1792 | return -EINVAL; | ||
1793 | fmt->width = 720; | ||
1794 | /* valid signal */ | ||
1795 | if (state->norm & V4L2_STD_525_60) | ||
1796 | fmt->height = 480; | ||
1797 | else | ||
1798 | fmt->height = 576; | ||
1799 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
1800 | return 0; | ||
1801 | } | ||
1802 | |||
1803 | if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) { | ||
1804 | fmt->colorspace = (state->timings.bt.height <= 576) ? | ||
1805 | V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709; | ||
1806 | } | ||
1807 | return 0; | ||
1808 | } | ||
1809 | |||
1810 | static void adv7842_irq_enable(struct v4l2_subdev *sd, bool enable) | ||
1811 | { | ||
1812 | if (enable) { | ||
1813 | /* Enable SSPD, STDI and CP locked/unlocked interrupts */ | ||
1814 | io_write(sd, 0x46, 0x9c); | ||
1815 | /* ESDP_50HZ_DET interrupt */ | ||
1816 | io_write(sd, 0x5a, 0x10); | ||
1817 | /* Enable CABLE_DET_A/B_ST (+5v) interrupt */ | ||
1818 | io_write(sd, 0x73, 0x03); | ||
1819 | /* Enable V_LOCKED and DE_REGEN_LCK interrupts */ | ||
1820 | io_write(sd, 0x78, 0x03); | ||
1821 | /* Enable SDP Standard Detection Change and SDP Video Detected */ | ||
1822 | io_write(sd, 0xa0, 0x09); | ||
1823 | } else { | ||
1824 | io_write(sd, 0x46, 0x0); | ||
1825 | io_write(sd, 0x5a, 0x0); | ||
1826 | io_write(sd, 0x73, 0x0); | ||
1827 | io_write(sd, 0x78, 0x0); | ||
1828 | io_write(sd, 0xa0, 0x0); | ||
1829 | } | ||
1830 | } | ||
1831 | |||
1832 | static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | ||
1833 | { | ||
1834 | struct adv7842_state *state = to_state(sd); | ||
1835 | u8 fmt_change_cp, fmt_change_digital, fmt_change_sdp; | ||
1836 | u8 irq_status[5]; | ||
1837 | u8 irq_cfg = io_read(sd, 0x40); | ||
1838 | |||
1839 | /* disable irq-pin output */ | ||
1840 | io_write(sd, 0x40, irq_cfg | 0x3); | ||
1841 | |||
1842 | /* read status */ | ||
1843 | irq_status[0] = io_read(sd, 0x43); | ||
1844 | irq_status[1] = io_read(sd, 0x57); | ||
1845 | irq_status[2] = io_read(sd, 0x70); | ||
1846 | irq_status[3] = io_read(sd, 0x75); | ||
1847 | irq_status[4] = io_read(sd, 0x9d); | ||
1848 | |||
1849 | /* and clear */ | ||
1850 | if (irq_status[0]) | ||
1851 | io_write(sd, 0x44, irq_status[0]); | ||
1852 | if (irq_status[1]) | ||
1853 | io_write(sd, 0x58, irq_status[1]); | ||
1854 | if (irq_status[2]) | ||
1855 | io_write(sd, 0x71, irq_status[2]); | ||
1856 | if (irq_status[3]) | ||
1857 | io_write(sd, 0x76, irq_status[3]); | ||
1858 | if (irq_status[4]) | ||
1859 | io_write(sd, 0x9e, irq_status[4]); | ||
1860 | |||
1861 | v4l2_dbg(1, debug, sd, "%s: irq %x, %x, %x, %x, %x\n", __func__, | ||
1862 | irq_status[0], irq_status[1], irq_status[2], | ||
1863 | irq_status[3], irq_status[4]); | ||
1864 | |||
1865 | /* format change CP */ | ||
1866 | fmt_change_cp = irq_status[0] & 0x9c; | ||
1867 | |||
1868 | /* format change SDP */ | ||
1869 | if (state->mode == ADV7842_MODE_SDP) | ||
1870 | fmt_change_sdp = (irq_status[1] & 0x30) | (irq_status[4] & 0x09); | ||
1871 | else | ||
1872 | fmt_change_sdp = 0; | ||
1873 | |||
1874 | /* digital format CP */ | ||
1875 | if (is_digital_input(sd)) | ||
1876 | fmt_change_digital = irq_status[3] & 0x03; | ||
1877 | else | ||
1878 | fmt_change_digital = 0; | ||
1879 | |||
1880 | /* notify */ | ||
1881 | if (fmt_change_cp || fmt_change_digital || fmt_change_sdp) { | ||
1882 | v4l2_dbg(1, debug, sd, | ||
1883 | "%s: fmt_change_cp = 0x%x, fmt_change_digital = 0x%x, fmt_change_sdp = 0x%x\n", | ||
1884 | __func__, fmt_change_cp, fmt_change_digital, | ||
1885 | fmt_change_sdp); | ||
1886 | v4l2_subdev_notify(sd, ADV7842_FMT_CHANGE, NULL); | ||
1887 | } | ||
1888 | |||
1889 | /* 5v cable detect */ | ||
1890 | if (irq_status[2]) | ||
1891 | adv7842_s_detect_tx_5v_ctrl(sd); | ||
1892 | |||
1893 | if (handled) | ||
1894 | *handled = true; | ||
1895 | |||
1896 | /* re-enable irq-pin output */ | ||
1897 | io_write(sd, 0x40, irq_cfg); | ||
1898 | |||
1899 | return 0; | ||
1900 | } | ||
1901 | |||
1902 | static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *e) | ||
1903 | { | ||
1904 | struct adv7842_state *state = to_state(sd); | ||
1905 | int err = 0; | ||
1906 | |||
1907 | if (e->pad > 2) | ||
1908 | return -EINVAL; | ||
1909 | if (e->start_block != 0) | ||
1910 | return -EINVAL; | ||
1911 | if (e->blocks > 2) | ||
1912 | return -E2BIG; | ||
1913 | if (!e->edid) | ||
1914 | return -EINVAL; | ||
1915 | |||
1916 | /* todo, per edid */ | ||
1917 | state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15], | ||
1918 | e->edid[0x16]); | ||
1919 | |||
1920 | if (e->pad == 2) { | ||
1921 | memset(&state->vga_edid.edid, 0, 256); | ||
1922 | state->vga_edid.present = e->blocks ? 0x1 : 0x0; | ||
1923 | memcpy(&state->vga_edid.edid, e->edid, 128 * e->blocks); | ||
1924 | err = edid_write_vga_segment(sd); | ||
1925 | } else { | ||
1926 | u32 mask = 0x1<<e->pad; | ||
1927 | memset(&state->hdmi_edid.edid, 0, 256); | ||
1928 | if (e->blocks) | ||
1929 | state->hdmi_edid.present |= mask; | ||
1930 | else | ||
1931 | state->hdmi_edid.present &= ~mask; | ||
1932 | memcpy(&state->hdmi_edid.edid, e->edid, 128*e->blocks); | ||
1933 | err = edid_write_hdmi_segment(sd, e->pad); | ||
1934 | } | ||
1935 | if (err < 0) | ||
1936 | v4l2_err(sd, "error %d writing edid on port %d\n", err, e->pad); | ||
1937 | return err; | ||
1938 | } | ||
1939 | |||
1940 | /*********** avi info frame CEA-861-E **************/ | ||
1941 | /* TODO move to common library */ | ||
1942 | |||
1943 | struct avi_info_frame { | ||
1944 | uint8_t f17; | ||
1945 | uint8_t y10; | ||
1946 | uint8_t a0; | ||
1947 | uint8_t b10; | ||
1948 | uint8_t s10; | ||
1949 | uint8_t c10; | ||
1950 | uint8_t m10; | ||
1951 | uint8_t r3210; | ||
1952 | uint8_t itc; | ||
1953 | uint8_t ec210; | ||
1954 | uint8_t q10; | ||
1955 | uint8_t sc10; | ||
1956 | uint8_t f47; | ||
1957 | uint8_t vic; | ||
1958 | uint8_t yq10; | ||
1959 | uint8_t cn10; | ||
1960 | uint8_t pr3210; | ||
1961 | uint16_t etb; | ||
1962 | uint16_t sbb; | ||
1963 | uint16_t elb; | ||
1964 | uint16_t srb; | ||
1965 | }; | ||
1966 | |||
1967 | static const char *y10_txt[4] = { | ||
1968 | "RGB", | ||
1969 | "YCbCr 4:2:2", | ||
1970 | "YCbCr 4:4:4", | ||
1971 | "Future", | ||
1972 | }; | ||
1973 | |||
1974 | static const char *c10_txt[4] = { | ||
1975 | "No Data", | ||
1976 | "SMPTE 170M", | ||
1977 | "ITU-R 709", | ||
1978 | "Extended Colorimetry information valied", | ||
1979 | }; | ||
1980 | |||
1981 | static const char *itc_txt[2] = { | ||
1982 | "No Data", | ||
1983 | "IT content", | ||
1984 | }; | ||
1985 | |||
1986 | static const char *ec210_txt[8] = { | ||
1987 | "xvYCC601", | ||
1988 | "xvYCC709", | ||
1989 | "sYCC601", | ||
1990 | "AdobeYCC601", | ||
1991 | "AdobeRGB", | ||
1992 | "5 reserved", | ||
1993 | "6 reserved", | ||
1994 | "7 reserved", | ||
1995 | }; | ||
1996 | |||
1997 | static const char *q10_txt[4] = { | ||
1998 | "Default", | ||
1999 | "Limited Range", | ||
2000 | "Full Range", | ||
2001 | "Reserved", | ||
2002 | }; | ||
2003 | |||
2004 | static void parse_avi_infoframe(struct v4l2_subdev *sd, uint8_t *buf, | ||
2005 | struct avi_info_frame *avi) | ||
2006 | { | ||
2007 | avi->f17 = (buf[1] >> 7) & 0x1; | ||
2008 | avi->y10 = (buf[1] >> 5) & 0x3; | ||
2009 | avi->a0 = (buf[1] >> 4) & 0x1; | ||
2010 | avi->b10 = (buf[1] >> 2) & 0x3; | ||
2011 | avi->s10 = buf[1] & 0x3; | ||
2012 | avi->c10 = (buf[2] >> 6) & 0x3; | ||
2013 | avi->m10 = (buf[2] >> 4) & 0x3; | ||
2014 | avi->r3210 = buf[2] & 0xf; | ||
2015 | avi->itc = (buf[3] >> 7) & 0x1; | ||
2016 | avi->ec210 = (buf[3] >> 4) & 0x7; | ||
2017 | avi->q10 = (buf[3] >> 2) & 0x3; | ||
2018 | avi->sc10 = buf[3] & 0x3; | ||
2019 | avi->f47 = (buf[4] >> 7) & 0x1; | ||
2020 | avi->vic = buf[4] & 0x7f; | ||
2021 | avi->yq10 = (buf[5] >> 6) & 0x3; | ||
2022 | avi->cn10 = (buf[5] >> 4) & 0x3; | ||
2023 | avi->pr3210 = buf[5] & 0xf; | ||
2024 | avi->etb = buf[6] + 256*buf[7]; | ||
2025 | avi->sbb = buf[8] + 256*buf[9]; | ||
2026 | avi->elb = buf[10] + 256*buf[11]; | ||
2027 | avi->srb = buf[12] + 256*buf[13]; | ||
2028 | } | ||
2029 | |||
2030 | static void print_avi_infoframe(struct v4l2_subdev *sd) | ||
2031 | { | ||
2032 | int i; | ||
2033 | uint8_t buf[14]; | ||
2034 | uint8_t avi_inf_len; | ||
2035 | struct avi_info_frame avi; | ||
2036 | |||
2037 | if (!(hdmi_read(sd, 0x05) & 0x80)) { | ||
2038 | v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n"); | ||
2039 | return; | ||
2040 | } | ||
2041 | if (!(io_read(sd, 0x60) & 0x01)) { | ||
2042 | v4l2_info(sd, "AVI infoframe not received\n"); | ||
2043 | return; | ||
2044 | } | ||
2045 | |||
2046 | if (io_read(sd, 0x88) & 0x10) { | ||
2047 | /* Note: the ADV7842 calculated incorrect checksums for InfoFrames | ||
2048 | with a length of 14 or 15. See the ADV7842 Register Settings | ||
2049 | Recommendations document for more details. */ | ||
2050 | v4l2_info(sd, "AVI infoframe checksum error\n"); | ||
2051 | return; | ||
2052 | } | ||
2053 | |||
2054 | avi_inf_len = infoframe_read(sd, 0xe2); | ||
2055 | v4l2_info(sd, "AVI infoframe version %d (%d byte)\n", | ||
2056 | infoframe_read(sd, 0xe1), avi_inf_len); | ||
2057 | |||
2058 | if (infoframe_read(sd, 0xe1) != 0x02) | ||
2059 | return; | ||
2060 | |||
2061 | for (i = 0; i < 14; i++) | ||
2062 | buf[i] = infoframe_read(sd, i); | ||
2063 | |||
2064 | v4l2_info(sd, "\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
2065 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], | ||
2066 | buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]); | ||
2067 | |||
2068 | parse_avi_infoframe(sd, buf, &avi); | ||
2069 | |||
2070 | if (avi.vic) | ||
2071 | v4l2_info(sd, "\tVIC: %d\n", avi.vic); | ||
2072 | if (avi.itc) | ||
2073 | v4l2_info(sd, "\t%s\n", itc_txt[avi.itc]); | ||
2074 | |||
2075 | if (avi.y10) | ||
2076 | v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], !avi.c10 ? "" : | ||
2077 | (avi.c10 == 0x3 ? ec210_txt[avi.ec210] : c10_txt[avi.c10])); | ||
2078 | else | ||
2079 | v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], q10_txt[avi.q10]); | ||
2080 | } | ||
2081 | |||
2082 | static const char * const prim_mode_txt[] = { | ||
2083 | "SDP", | ||
2084 | "Component", | ||
2085 | "Graphics", | ||
2086 | "Reserved", | ||
2087 | "CVBS & HDMI AUDIO", | ||
2088 | "HDMI-Comp", | ||
2089 | "HDMI-GR", | ||
2090 | "Reserved", | ||
2091 | "Reserved", | ||
2092 | "Reserved", | ||
2093 | "Reserved", | ||
2094 | "Reserved", | ||
2095 | "Reserved", | ||
2096 | "Reserved", | ||
2097 | "Reserved", | ||
2098 | "Reserved", | ||
2099 | }; | ||
2100 | |||
2101 | static int adv7842_sdp_log_status(struct v4l2_subdev *sd) | ||
2102 | { | ||
2103 | /* SDP (Standard definition processor) block */ | ||
2104 | uint8_t sdp_signal_detected = sdp_read(sd, 0x5A) & 0x01; | ||
2105 | |||
2106 | v4l2_info(sd, "Chip powered %s\n", no_power(sd) ? "off" : "on"); | ||
2107 | v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n", | ||
2108 | io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f); | ||
2109 | |||
2110 | v4l2_info(sd, "SDP: free run: %s\n", | ||
2111 | (sdp_read(sd, 0x56) & 0x01) ? "on" : "off"); | ||
2112 | v4l2_info(sd, "SDP: %s\n", sdp_signal_detected ? | ||
2113 | "valid SD/PR signal detected" : "invalid/no signal"); | ||
2114 | if (sdp_signal_detected) { | ||
2115 | static const char * const sdp_std_txt[] = { | ||
2116 | "NTSC-M/J", | ||
2117 | "1?", | ||
2118 | "NTSC-443", | ||
2119 | "60HzSECAM", | ||
2120 | "PAL-M", | ||
2121 | "5?", | ||
2122 | "PAL-60", | ||
2123 | "7?", "8?", "9?", "a?", "b?", | ||
2124 | "PAL-CombN", | ||
2125 | "d?", | ||
2126 | "PAL-BGHID", | ||
2127 | "SECAM" | ||
2128 | }; | ||
2129 | v4l2_info(sd, "SDP: standard %s\n", | ||
2130 | sdp_std_txt[sdp_read(sd, 0x52) & 0x0f]); | ||
2131 | v4l2_info(sd, "SDP: %s\n", | ||
2132 | (sdp_read(sd, 0x59) & 0x08) ? "50Hz" : "60Hz"); | ||
2133 | v4l2_info(sd, "SDP: %s\n", | ||
2134 | (sdp_read(sd, 0x57) & 0x08) ? "Interlaced" : "Progressive"); | ||
2135 | v4l2_info(sd, "SDP: deinterlacer %s\n", | ||
2136 | (sdp_read(sd, 0x12) & 0x08) ? "enabled" : "disabled"); | ||
2137 | v4l2_info(sd, "SDP: csc %s mode\n", | ||
2138 | (sdp_io_read(sd, 0xe0) & 0x40) ? "auto" : "manual"); | ||
2139 | } | ||
2140 | return 0; | ||
2141 | } | ||
2142 | |||
2143 | static int adv7842_cp_log_status(struct v4l2_subdev *sd) | ||
2144 | { | ||
2145 | /* CP block */ | ||
2146 | struct adv7842_state *state = to_state(sd); | ||
2147 | struct v4l2_dv_timings timings; | ||
2148 | uint8_t reg_io_0x02 = io_read(sd, 0x02); | ||
2149 | uint8_t reg_io_0x21 = io_read(sd, 0x21); | ||
2150 | uint8_t reg_rep_0x77 = rep_read(sd, 0x77); | ||
2151 | uint8_t reg_rep_0x7d = rep_read(sd, 0x7d); | ||
2152 | bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01; | ||
2153 | bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01; | ||
2154 | bool audio_mute = io_read(sd, 0x65) & 0x40; | ||
2155 | |||
2156 | static const char * const csc_coeff_sel_rb[16] = { | ||
2157 | "bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB", | ||
2158 | "reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709", | ||
2159 | "reserved", "YPbPr709 -> YPbPr601", "YPbPr601 -> YPbPr709", | ||
2160 | "reserved", "reserved", "reserved", "reserved", "manual" | ||
2161 | }; | ||
2162 | static const char * const input_color_space_txt[16] = { | ||
2163 | "RGB limited range (16-235)", "RGB full range (0-255)", | ||
2164 | "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)", | ||
2165 | "XvYCC Bt.601", "XvYCC Bt.709", | ||
2166 | "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)", | ||
2167 | "invalid", "invalid", "invalid", "invalid", "invalid", | ||
2168 | "invalid", "invalid", "automatic" | ||
2169 | }; | ||
2170 | static const char * const rgb_quantization_range_txt[] = { | ||
2171 | "Automatic", | ||
2172 | "RGB limited range (16-235)", | ||
2173 | "RGB full range (0-255)", | ||
2174 | }; | ||
2175 | static const char * const deep_color_mode_txt[4] = { | ||
2176 | "8-bits per channel", | ||
2177 | "10-bits per channel", | ||
2178 | "12-bits per channel", | ||
2179 | "16-bits per channel (not supported)" | ||
2180 | }; | ||
2181 | |||
2182 | v4l2_info(sd, "-----Chip status-----\n"); | ||
2183 | v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); | ||
2184 | v4l2_info(sd, "Connector type: %s\n", state->connector_hdmi ? | ||
2185 | "HDMI" : (is_digital_input(sd) ? "DVI-D" : "DVI-A")); | ||
2186 | v4l2_info(sd, "HDMI/DVI-D port selected: %s\n", | ||
2187 | state->hdmi_port_a ? "A" : "B"); | ||
2188 | v4l2_info(sd, "EDID A %s, B %s\n", | ||
2189 | ((reg_rep_0x7d & 0x04) && (reg_rep_0x77 & 0x04)) ? | ||
2190 | "enabled" : "disabled", | ||
2191 | ((reg_rep_0x7d & 0x08) && (reg_rep_0x77 & 0x08)) ? | ||
2192 | "enabled" : "disabled"); | ||
2193 | v4l2_info(sd, "HPD A %s, B %s\n", | ||
2194 | reg_io_0x21 & 0x02 ? "enabled" : "disabled", | ||
2195 | reg_io_0x21 & 0x01 ? "enabled" : "disabled"); | ||
2196 | v4l2_info(sd, "CEC %s\n", !!(cec_read(sd, 0x2a) & 0x01) ? | ||
2197 | "enabled" : "disabled"); | ||
2198 | |||
2199 | v4l2_info(sd, "-----Signal status-----\n"); | ||
2200 | if (state->hdmi_port_a) { | ||
2201 | v4l2_info(sd, "Cable detected (+5V power): %s\n", | ||
2202 | io_read(sd, 0x6f) & 0x02 ? "true" : "false"); | ||
2203 | v4l2_info(sd, "TMDS signal detected: %s\n", | ||
2204 | (io_read(sd, 0x6a) & 0x02) ? "true" : "false"); | ||
2205 | v4l2_info(sd, "TMDS signal locked: %s\n", | ||
2206 | (io_read(sd, 0x6a) & 0x20) ? "true" : "false"); | ||
2207 | } else { | ||
2208 | v4l2_info(sd, "Cable detected (+5V power):%s\n", | ||
2209 | io_read(sd, 0x6f) & 0x01 ? "true" : "false"); | ||
2210 | v4l2_info(sd, "TMDS signal detected: %s\n", | ||
2211 | (io_read(sd, 0x6a) & 0x01) ? "true" : "false"); | ||
2212 | v4l2_info(sd, "TMDS signal locked: %s\n", | ||
2213 | (io_read(sd, 0x6a) & 0x10) ? "true" : "false"); | ||
2214 | } | ||
2215 | v4l2_info(sd, "CP free run: %s\n", | ||
2216 | (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off")); | ||
2217 | v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n", | ||
2218 | io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f, | ||
2219 | (io_read(sd, 0x01) & 0x70) >> 4); | ||
2220 | |||
2221 | v4l2_info(sd, "-----Video Timings-----\n"); | ||
2222 | if (no_cp_signal(sd)) { | ||
2223 | v4l2_info(sd, "STDI: not locked\n"); | ||
2224 | } else { | ||
2225 | uint32_t bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2); | ||
2226 | uint32_t lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4); | ||
2227 | uint32_t lcvs = cp_read(sd, 0xb3) >> 3; | ||
2228 | uint32_t fcl = ((cp_read(sd, 0xb8) & 0x1f) << 8) | cp_read(sd, 0xb9); | ||
2229 | char hs_pol = ((cp_read(sd, 0xb5) & 0x10) ? | ||
2230 | ((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x'); | ||
2231 | char vs_pol = ((cp_read(sd, 0xb5) & 0x40) ? | ||
2232 | ((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x'); | ||
2233 | v4l2_info(sd, | ||
2234 | "STDI: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, fcl = %d, %s, %chsync, %cvsync\n", | ||
2235 | lcf, bl, lcvs, fcl, | ||
2236 | (cp_read(sd, 0xb1) & 0x40) ? | ||
2237 | "interlaced" : "progressive", | ||
2238 | hs_pol, vs_pol); | ||
2239 | } | ||
2240 | if (adv7842_query_dv_timings(sd, &timings)) | ||
2241 | v4l2_info(sd, "No video detected\n"); | ||
2242 | else | ||
2243 | v4l2_print_dv_timings(sd->name, "Detected format: ", | ||
2244 | &timings, true); | ||
2245 | v4l2_print_dv_timings(sd->name, "Configured format: ", | ||
2246 | &state->timings, true); | ||
2247 | |||
2248 | if (no_cp_signal(sd)) | ||
2249 | return 0; | ||
2250 | |||
2251 | v4l2_info(sd, "-----Color space-----\n"); | ||
2252 | v4l2_info(sd, "RGB quantization range ctrl: %s\n", | ||
2253 | rgb_quantization_range_txt[state->rgb_quantization_range]); | ||
2254 | v4l2_info(sd, "Input color space: %s\n", | ||
2255 | input_color_space_txt[reg_io_0x02 >> 4]); | ||
2256 | v4l2_info(sd, "Output color space: %s %s, saturator %s\n", | ||
2257 | (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", | ||
2258 | (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", | ||
2259 | ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ? | ||
2260 | "enabled" : "disabled"); | ||
2261 | v4l2_info(sd, "Color space conversion: %s\n", | ||
2262 | csc_coeff_sel_rb[cp_read(sd, 0xf4) >> 4]); | ||
2263 | |||
2264 | if (!is_digital_input(sd)) | ||
2265 | return 0; | ||
2266 | |||
2267 | v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D"); | ||
2268 | v4l2_info(sd, "HDCP encrypted content: %s\n", | ||
2269 | (hdmi_read(sd, 0x05) & 0x40) ? "true" : "false"); | ||
2270 | v4l2_info(sd, "HDCP keys read: %s%s\n", | ||
2271 | (hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no", | ||
2272 | (hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : ""); | ||
2273 | if (!is_hdmi(sd)) | ||
2274 | return 0; | ||
2275 | |||
2276 | v4l2_info(sd, "Audio: pll %s, samples %s, %s\n", | ||
2277 | audio_pll_locked ? "locked" : "not locked", | ||
2278 | audio_sample_packet_detect ? "detected" : "not detected", | ||
2279 | audio_mute ? "muted" : "enabled"); | ||
2280 | if (audio_pll_locked && audio_sample_packet_detect) { | ||
2281 | v4l2_info(sd, "Audio format: %s\n", | ||
2282 | (hdmi_read(sd, 0x07) & 0x40) ? "multi-channel" : "stereo"); | ||
2283 | } | ||
2284 | v4l2_info(sd, "Audio CTS: %u\n", (hdmi_read(sd, 0x5b) << 12) + | ||
2285 | (hdmi_read(sd, 0x5c) << 8) + | ||
2286 | (hdmi_read(sd, 0x5d) & 0xf0)); | ||
2287 | v4l2_info(sd, "Audio N: %u\n", ((hdmi_read(sd, 0x5d) & 0x0f) << 16) + | ||
2288 | (hdmi_read(sd, 0x5e) << 8) + | ||
2289 | hdmi_read(sd, 0x5f)); | ||
2290 | v4l2_info(sd, "AV Mute: %s\n", | ||
2291 | (hdmi_read(sd, 0x04) & 0x40) ? "on" : "off"); | ||
2292 | v4l2_info(sd, "Deep color mode: %s\n", | ||
2293 | deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]); | ||
2294 | |||
2295 | print_avi_infoframe(sd); | ||
2296 | return 0; | ||
2297 | } | ||
2298 | |||
2299 | static int adv7842_log_status(struct v4l2_subdev *sd) | ||
2300 | { | ||
2301 | struct adv7842_state *state = to_state(sd); | ||
2302 | |||
2303 | if (state->mode == ADV7842_MODE_SDP) | ||
2304 | return adv7842_sdp_log_status(sd); | ||
2305 | return adv7842_cp_log_status(sd); | ||
2306 | } | ||
2307 | |||
2308 | static int adv7842_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) | ||
2309 | { | ||
2310 | struct adv7842_state *state = to_state(sd); | ||
2311 | |||
2312 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
2313 | |||
2314 | if (state->mode != ADV7842_MODE_SDP) | ||
2315 | return -ENODATA; | ||
2316 | |||
2317 | if (!(sdp_read(sd, 0x5A) & 0x01)) { | ||
2318 | *std = 0; | ||
2319 | v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__); | ||
2320 | return 0; | ||
2321 | } | ||
2322 | |||
2323 | switch (sdp_read(sd, 0x52) & 0x0f) { | ||
2324 | case 0: | ||
2325 | /* NTSC-M/J */ | ||
2326 | *std &= V4L2_STD_NTSC; | ||
2327 | break; | ||
2328 | case 2: | ||
2329 | /* NTSC-443 */ | ||
2330 | *std &= V4L2_STD_NTSC_443; | ||
2331 | break; | ||
2332 | case 3: | ||
2333 | /* 60HzSECAM */ | ||
2334 | *std &= V4L2_STD_SECAM; | ||
2335 | break; | ||
2336 | case 4: | ||
2337 | /* PAL-M */ | ||
2338 | *std &= V4L2_STD_PAL_M; | ||
2339 | break; | ||
2340 | case 6: | ||
2341 | /* PAL-60 */ | ||
2342 | *std &= V4L2_STD_PAL_60; | ||
2343 | break; | ||
2344 | case 0xc: | ||
2345 | /* PAL-CombN */ | ||
2346 | *std &= V4L2_STD_PAL_Nc; | ||
2347 | break; | ||
2348 | case 0xe: | ||
2349 | /* PAL-BGHID */ | ||
2350 | *std &= V4L2_STD_PAL; | ||
2351 | break; | ||
2352 | case 0xf: | ||
2353 | /* SECAM */ | ||
2354 | *std &= V4L2_STD_SECAM; | ||
2355 | break; | ||
2356 | default: | ||
2357 | *std &= V4L2_STD_ALL; | ||
2358 | break; | ||
2359 | } | ||
2360 | return 0; | ||
2361 | } | ||
2362 | |||
2363 | static int adv7842_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) | ||
2364 | { | ||
2365 | struct adv7842_state *state = to_state(sd); | ||
2366 | |||
2367 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
2368 | |||
2369 | if (state->mode != ADV7842_MODE_SDP) | ||
2370 | return -ENODATA; | ||
2371 | |||
2372 | if (norm & V4L2_STD_ALL) { | ||
2373 | state->norm = norm; | ||
2374 | return 0; | ||
2375 | } | ||
2376 | return -EINVAL; | ||
2377 | } | ||
2378 | |||
2379 | static int adv7842_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm) | ||
2380 | { | ||
2381 | struct adv7842_state *state = to_state(sd); | ||
2382 | |||
2383 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
2384 | |||
2385 | if (state->mode != ADV7842_MODE_SDP) | ||
2386 | return -ENODATA; | ||
2387 | |||
2388 | *norm = state->norm; | ||
2389 | return 0; | ||
2390 | } | ||
2391 | |||
2392 | /* ----------------------------------------------------------------------- */ | ||
2393 | |||
2394 | static int adv7842_core_init(struct v4l2_subdev *sd, | ||
2395 | const struct adv7842_platform_data *pdata) | ||
2396 | { | ||
2397 | hdmi_write(sd, 0x48, | ||
2398 | (pdata->disable_pwrdnb ? 0x80 : 0) | | ||
2399 | (pdata->disable_cable_det_rst ? 0x40 : 0)); | ||
2400 | |||
2401 | disable_input(sd); | ||
2402 | |||
2403 | /* power */ | ||
2404 | io_write(sd, 0x0c, 0x42); /* Power up part and power down VDP */ | ||
2405 | io_write(sd, 0x15, 0x80); /* Power up pads */ | ||
2406 | |||
2407 | /* video format */ | ||
2408 | io_write(sd, 0x02, | ||
2409 | pdata->inp_color_space << 4 | | ||
2410 | pdata->alt_gamma << 3 | | ||
2411 | pdata->op_656_range << 2 | | ||
2412 | pdata->rgb_out << 1 | | ||
2413 | pdata->alt_data_sat << 0); | ||
2414 | io_write(sd, 0x03, pdata->op_format_sel); | ||
2415 | io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5); | ||
2416 | io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 | | ||
2417 | pdata->insert_av_codes << 2 | | ||
2418 | pdata->replicate_av_codes << 1 | | ||
2419 | pdata->invert_cbcr << 0); | ||
2420 | |||
2421 | /* Drive strength */ | ||
2422 | io_write_and_or(sd, 0x14, 0xc0, pdata->drive_strength.data<<4 | | ||
2423 | pdata->drive_strength.clock<<2 | | ||
2424 | pdata->drive_strength.sync); | ||
2425 | |||
2426 | /* HDMI free run */ | ||
2427 | cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); | ||
2428 | |||
2429 | /* TODO from platform data */ | ||
2430 | cp_write(sd, 0x69, 0x14); /* Enable CP CSC */ | ||
2431 | io_write(sd, 0x06, 0xa6); /* positive VS and HS and DE */ | ||
2432 | cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */ | ||
2433 | afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */ | ||
2434 | |||
2435 | afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */ | ||
2436 | io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4); | ||
2437 | |||
2438 | sdp_csc_coeff(sd, &pdata->sdp_csc_coeff); | ||
2439 | |||
2440 | if (pdata->sdp_io_sync.adjust) { | ||
2441 | const struct adv7842_sdp_io_sync_adjustment *s = &pdata->sdp_io_sync; | ||
2442 | sdp_io_write(sd, 0x94, (s->hs_beg>>8) & 0xf); | ||
2443 | sdp_io_write(sd, 0x95, s->hs_beg & 0xff); | ||
2444 | sdp_io_write(sd, 0x96, (s->hs_width>>8) & 0xf); | ||
2445 | sdp_io_write(sd, 0x97, s->hs_width & 0xff); | ||
2446 | sdp_io_write(sd, 0x98, (s->de_beg>>8) & 0xf); | ||
2447 | sdp_io_write(sd, 0x99, s->de_beg & 0xff); | ||
2448 | sdp_io_write(sd, 0x9a, (s->de_end>>8) & 0xf); | ||
2449 | sdp_io_write(sd, 0x9b, s->de_end & 0xff); | ||
2450 | } | ||
2451 | |||
2452 | /* todo, improve settings for sdram */ | ||
2453 | if (pdata->sd_ram_size >= 128) { | ||
2454 | sdp_write(sd, 0x12, 0x0d); /* Frame TBC,3D comb enabled */ | ||
2455 | if (pdata->sd_ram_ddr) { | ||
2456 | /* SDP setup for the AD eval board */ | ||
2457 | sdp_io_write(sd, 0x6f, 0x00); /* DDR mode */ | ||
2458 | sdp_io_write(sd, 0x75, 0x0a); /* 128 MB memory size */ | ||
2459 | sdp_io_write(sd, 0x7a, 0xa5); /* Timing Adjustment */ | ||
2460 | sdp_io_write(sd, 0x7b, 0x8f); /* Timing Adjustment */ | ||
2461 | sdp_io_write(sd, 0x60, 0x01); /* SDRAM reset */ | ||
2462 | } else { | ||
2463 | sdp_io_write(sd, 0x75, 0x0a); /* 64 MB memory size ?*/ | ||
2464 | sdp_io_write(sd, 0x74, 0x00); /* must be zero for sdr sdram */ | ||
2465 | sdp_io_write(sd, 0x79, 0x33); /* CAS latency to 3, | ||
2466 | depends on memory */ | ||
2467 | sdp_io_write(sd, 0x6f, 0x01); /* SDR mode */ | ||
2468 | sdp_io_write(sd, 0x7a, 0xa5); /* Timing Adjustment */ | ||
2469 | sdp_io_write(sd, 0x7b, 0x8f); /* Timing Adjustment */ | ||
2470 | sdp_io_write(sd, 0x60, 0x01); /* SDRAM reset */ | ||
2471 | } | ||
2472 | } else { | ||
2473 | /* | ||
2474 | * Manual UG-214, rev 0 is bit confusing on this bit | ||
2475 | * but a '1' disables any signal if the Ram is active. | ||
2476 | */ | ||
2477 | sdp_io_write(sd, 0x29, 0x10); /* Tristate memory interface */ | ||
2478 | } | ||
2479 | |||
2480 | select_input(sd, pdata->vid_std_select); | ||
2481 | |||
2482 | enable_input(sd); | ||
2483 | |||
2484 | /* disable I2C access to internal EDID ram from HDMI DDC ports */ | ||
2485 | rep_write_and_or(sd, 0x77, 0xf3, 0x00); | ||
2486 | |||
2487 | hdmi_write(sd, 0x69, 0xa3); /* HPA manual */ | ||
2488 | /* HPA disable on port A and B */ | ||
2489 | io_write_and_or(sd, 0x20, 0xcf, 0x00); | ||
2490 | |||
2491 | /* LLC */ | ||
2492 | /* Set phase to 16. TODO: get this from platform_data */ | ||
2493 | io_write(sd, 0x19, 0x90); | ||
2494 | io_write(sd, 0x33, 0x40); | ||
2495 | |||
2496 | /* interrupts */ | ||
2497 | io_write(sd, 0x40, 0xe2); /* Configure INT1 */ | ||
2498 | |||
2499 | adv7842_irq_enable(sd, true); | ||
2500 | |||
2501 | return v4l2_ctrl_handler_setup(sd->ctrl_handler); | ||
2502 | } | ||
2503 | |||
2504 | /* ----------------------------------------------------------------------- */ | ||
2505 | |||
2506 | static int adv7842_ddr_ram_test(struct v4l2_subdev *sd) | ||
2507 | { | ||
2508 | /* | ||
2509 | * From ADV784x external Memory test.pdf | ||
2510 | * | ||
2511 | * Reset must just been performed before running test. | ||
2512 | * Recommended to reset after test. | ||
2513 | */ | ||
2514 | int i; | ||
2515 | int pass = 0; | ||
2516 | int fail = 0; | ||
2517 | int complete = 0; | ||
2518 | |||
2519 | io_write(sd, 0x00, 0x01); /* Program SDP 4x1 */ | ||
2520 | io_write(sd, 0x01, 0x00); /* Program SDP mode */ | ||
2521 | afe_write(sd, 0x80, 0x92); /* SDP Recommeneded Write */ | ||
2522 | afe_write(sd, 0x9B, 0x01); /* SDP Recommeneded Write ADV7844ES1 */ | ||
2523 | afe_write(sd, 0x9C, 0x60); /* SDP Recommeneded Write ADV7844ES1 */ | ||
2524 | afe_write(sd, 0x9E, 0x02); /* SDP Recommeneded Write ADV7844ES1 */ | ||
2525 | afe_write(sd, 0xA0, 0x0B); /* SDP Recommeneded Write ADV7844ES1 */ | ||
2526 | afe_write(sd, 0xC3, 0x02); /* Memory BIST Initialisation */ | ||
2527 | io_write(sd, 0x0C, 0x40); /* Power up ADV7844 */ | ||
2528 | io_write(sd, 0x15, 0xBA); /* Enable outputs */ | ||
2529 | sdp_write(sd, 0x12, 0x00); /* Disable 3D comb, Frame TBC & 3DNR */ | ||
2530 | io_write(sd, 0xFF, 0x04); /* Reset memory controller */ | ||
2531 | |||
2532 | mdelay(5); | ||
2533 | |||
2534 | sdp_write(sd, 0x12, 0x00); /* Disable 3D Comb, Frame TBC & 3DNR */ | ||
2535 | sdp_io_write(sd, 0x2A, 0x01); /* Memory BIST Initialisation */ | ||
2536 | sdp_io_write(sd, 0x7c, 0x19); /* Memory BIST Initialisation */ | ||
2537 | sdp_io_write(sd, 0x80, 0x87); /* Memory BIST Initialisation */ | ||
2538 | sdp_io_write(sd, 0x81, 0x4a); /* Memory BIST Initialisation */ | ||
2539 | sdp_io_write(sd, 0x82, 0x2c); /* Memory BIST Initialisation */ | ||
2540 | sdp_io_write(sd, 0x83, 0x0e); /* Memory BIST Initialisation */ | ||
2541 | sdp_io_write(sd, 0x84, 0x94); /* Memory BIST Initialisation */ | ||
2542 | sdp_io_write(sd, 0x85, 0x62); /* Memory BIST Initialisation */ | ||
2543 | sdp_io_write(sd, 0x7d, 0x00); /* Memory BIST Initialisation */ | ||
2544 | sdp_io_write(sd, 0x7e, 0x1a); /* Memory BIST Initialisation */ | ||
2545 | |||
2546 | mdelay(5); | ||
2547 | |||
2548 | sdp_io_write(sd, 0xd9, 0xd5); /* Enable BIST Test */ | ||
2549 | sdp_write(sd, 0x12, 0x05); /* Enable FRAME TBC & 3D COMB */ | ||
2550 | |||
2551 | mdelay(20); | ||
2552 | |||
2553 | for (i = 0; i < 10; i++) { | ||
2554 | u8 result = sdp_io_read(sd, 0xdb); | ||
2555 | if (result & 0x10) { | ||
2556 | complete++; | ||
2557 | if (result & 0x20) | ||
2558 | fail++; | ||
2559 | else | ||
2560 | pass++; | ||
2561 | } | ||
2562 | mdelay(20); | ||
2563 | } | ||
2564 | |||
2565 | v4l2_dbg(1, debug, sd, | ||
2566 | "Ram Test: completed %d of %d: pass %d, fail %d\n", | ||
2567 | complete, i, pass, fail); | ||
2568 | |||
2569 | if (!complete || fail) | ||
2570 | return -EIO; | ||
2571 | return 0; | ||
2572 | } | ||
2573 | |||
2574 | static void adv7842_rewrite_i2c_addresses(struct v4l2_subdev *sd, | ||
2575 | struct adv7842_platform_data *pdata) | ||
2576 | { | ||
2577 | io_write(sd, 0xf1, pdata->i2c_sdp << 1); | ||
2578 | io_write(sd, 0xf2, pdata->i2c_sdp_io << 1); | ||
2579 | io_write(sd, 0xf3, pdata->i2c_avlink << 1); | ||
2580 | io_write(sd, 0xf4, pdata->i2c_cec << 1); | ||
2581 | io_write(sd, 0xf5, pdata->i2c_infoframe << 1); | ||
2582 | |||
2583 | io_write(sd, 0xf8, pdata->i2c_afe << 1); | ||
2584 | io_write(sd, 0xf9, pdata->i2c_repeater << 1); | ||
2585 | io_write(sd, 0xfa, pdata->i2c_edid << 1); | ||
2586 | io_write(sd, 0xfb, pdata->i2c_hdmi << 1); | ||
2587 | |||
2588 | io_write(sd, 0xfd, pdata->i2c_cp << 1); | ||
2589 | io_write(sd, 0xfe, pdata->i2c_vdp << 1); | ||
2590 | } | ||
2591 | |||
2592 | static int adv7842_command_ram_test(struct v4l2_subdev *sd) | ||
2593 | { | ||
2594 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
2595 | struct adv7842_state *state = to_state(sd); | ||
2596 | struct adv7842_platform_data *pdata = client->dev.platform_data; | ||
2597 | int ret = 0; | ||
2598 | |||
2599 | if (!pdata) | ||
2600 | return -ENODEV; | ||
2601 | |||
2602 | if (!pdata->sd_ram_size || !pdata->sd_ram_ddr) { | ||
2603 | v4l2_info(sd, "no sdram or no ddr sdram\n"); | ||
2604 | return -EINVAL; | ||
2605 | } | ||
2606 | |||
2607 | main_reset(sd); | ||
2608 | |||
2609 | adv7842_rewrite_i2c_addresses(sd, pdata); | ||
2610 | |||
2611 | /* run ram test */ | ||
2612 | ret = adv7842_ddr_ram_test(sd); | ||
2613 | |||
2614 | main_reset(sd); | ||
2615 | |||
2616 | adv7842_rewrite_i2c_addresses(sd, pdata); | ||
2617 | |||
2618 | /* and re-init chip and state */ | ||
2619 | adv7842_core_init(sd, pdata); | ||
2620 | |||
2621 | disable_input(sd); | ||
2622 | |||
2623 | select_input(sd, state->vid_std_select); | ||
2624 | |||
2625 | enable_input(sd); | ||
2626 | |||
2627 | adv7842_s_dv_timings(sd, &state->timings); | ||
2628 | |||
2629 | edid_write_vga_segment(sd); | ||
2630 | edid_write_hdmi_segment(sd, 0); | ||
2631 | edid_write_hdmi_segment(sd, 1); | ||
2632 | |||
2633 | return ret; | ||
2634 | } | ||
2635 | |||
2636 | static long adv7842_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) | ||
2637 | { | ||
2638 | switch (cmd) { | ||
2639 | case ADV7842_CMD_RAM_TEST: | ||
2640 | return adv7842_command_ram_test(sd); | ||
2641 | } | ||
2642 | return -ENOTTY; | ||
2643 | } | ||
2644 | |||
2645 | /* ----------------------------------------------------------------------- */ | ||
2646 | |||
2647 | static const struct v4l2_ctrl_ops adv7842_ctrl_ops = { | ||
2648 | .s_ctrl = adv7842_s_ctrl, | ||
2649 | }; | ||
2650 | |||
2651 | static const struct v4l2_subdev_core_ops adv7842_core_ops = { | ||
2652 | .log_status = adv7842_log_status, | ||
2653 | .g_std = adv7842_g_std, | ||
2654 | .s_std = adv7842_s_std, | ||
2655 | .ioctl = adv7842_ioctl, | ||
2656 | .interrupt_service_routine = adv7842_isr, | ||
2657 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
2658 | .g_register = adv7842_g_register, | ||
2659 | .s_register = adv7842_s_register, | ||
2660 | #endif | ||
2661 | }; | ||
2662 | |||
2663 | static const struct v4l2_subdev_video_ops adv7842_video_ops = { | ||
2664 | .s_routing = adv7842_s_routing, | ||
2665 | .querystd = adv7842_querystd, | ||
2666 | .g_input_status = adv7842_g_input_status, | ||
2667 | .s_dv_timings = adv7842_s_dv_timings, | ||
2668 | .g_dv_timings = adv7842_g_dv_timings, | ||
2669 | .query_dv_timings = adv7842_query_dv_timings, | ||
2670 | .enum_dv_timings = adv7842_enum_dv_timings, | ||
2671 | .dv_timings_cap = adv7842_dv_timings_cap, | ||
2672 | .enum_mbus_fmt = adv7842_enum_mbus_fmt, | ||
2673 | .g_mbus_fmt = adv7842_g_mbus_fmt, | ||
2674 | .try_mbus_fmt = adv7842_g_mbus_fmt, | ||
2675 | .s_mbus_fmt = adv7842_g_mbus_fmt, | ||
2676 | }; | ||
2677 | |||
2678 | static const struct v4l2_subdev_pad_ops adv7842_pad_ops = { | ||
2679 | .set_edid = adv7842_set_edid, | ||
2680 | }; | ||
2681 | |||
2682 | static const struct v4l2_subdev_ops adv7842_ops = { | ||
2683 | .core = &adv7842_core_ops, | ||
2684 | .video = &adv7842_video_ops, | ||
2685 | .pad = &adv7842_pad_ops, | ||
2686 | }; | ||
2687 | |||
2688 | /* -------------------------- custom ctrls ---------------------------------- */ | ||
2689 | |||
2690 | static const struct v4l2_ctrl_config adv7842_ctrl_analog_sampling_phase = { | ||
2691 | .ops = &adv7842_ctrl_ops, | ||
2692 | .id = V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE, | ||
2693 | .name = "Analog Sampling Phase", | ||
2694 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
2695 | .min = 0, | ||
2696 | .max = 0x1f, | ||
2697 | .step = 1, | ||
2698 | .def = 0, | ||
2699 | }; | ||
2700 | |||
2701 | static const struct v4l2_ctrl_config adv7842_ctrl_free_run_color_manual = { | ||
2702 | .ops = &adv7842_ctrl_ops, | ||
2703 | .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL, | ||
2704 | .name = "Free Running Color, Manual", | ||
2705 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
2706 | .max = 1, | ||
2707 | .step = 1, | ||
2708 | .def = 1, | ||
2709 | }; | ||
2710 | |||
2711 | static const struct v4l2_ctrl_config adv7842_ctrl_free_run_color = { | ||
2712 | .ops = &adv7842_ctrl_ops, | ||
2713 | .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR, | ||
2714 | .name = "Free Running Color", | ||
2715 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
2716 | .max = 0xffffff, | ||
2717 | .step = 0x1, | ||
2718 | }; | ||
2719 | |||
2720 | |||
2721 | static void adv7842_unregister_clients(struct adv7842_state *state) | ||
2722 | { | ||
2723 | if (state->i2c_avlink) | ||
2724 | i2c_unregister_device(state->i2c_avlink); | ||
2725 | if (state->i2c_cec) | ||
2726 | i2c_unregister_device(state->i2c_cec); | ||
2727 | if (state->i2c_infoframe) | ||
2728 | i2c_unregister_device(state->i2c_infoframe); | ||
2729 | if (state->i2c_sdp_io) | ||
2730 | i2c_unregister_device(state->i2c_sdp_io); | ||
2731 | if (state->i2c_sdp) | ||
2732 | i2c_unregister_device(state->i2c_sdp); | ||
2733 | if (state->i2c_afe) | ||
2734 | i2c_unregister_device(state->i2c_afe); | ||
2735 | if (state->i2c_repeater) | ||
2736 | i2c_unregister_device(state->i2c_repeater); | ||
2737 | if (state->i2c_edid) | ||
2738 | i2c_unregister_device(state->i2c_edid); | ||
2739 | if (state->i2c_hdmi) | ||
2740 | i2c_unregister_device(state->i2c_hdmi); | ||
2741 | if (state->i2c_cp) | ||
2742 | i2c_unregister_device(state->i2c_cp); | ||
2743 | if (state->i2c_vdp) | ||
2744 | i2c_unregister_device(state->i2c_vdp); | ||
2745 | } | ||
2746 | |||
2747 | static struct i2c_client *adv7842_dummy_client(struct v4l2_subdev *sd, | ||
2748 | u8 addr, u8 io_reg) | ||
2749 | { | ||
2750 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
2751 | |||
2752 | io_write(sd, io_reg, addr << 1); | ||
2753 | return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1); | ||
2754 | } | ||
2755 | |||
2756 | static int adv7842_probe(struct i2c_client *client, | ||
2757 | const struct i2c_device_id *id) | ||
2758 | { | ||
2759 | struct adv7842_state *state; | ||
2760 | struct adv7842_platform_data *pdata = client->dev.platform_data; | ||
2761 | struct v4l2_ctrl_handler *hdl; | ||
2762 | struct v4l2_subdev *sd; | ||
2763 | u16 rev; | ||
2764 | int err; | ||
2765 | |||
2766 | /* Check if the adapter supports the needed features */ | ||
2767 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
2768 | return -EIO; | ||
2769 | |||
2770 | v4l_dbg(1, debug, client, "detecting adv7842 client on address 0x%x\n", | ||
2771 | client->addr << 1); | ||
2772 | |||
2773 | if (!pdata) { | ||
2774 | v4l_err(client, "No platform data!\n"); | ||
2775 | return -ENODEV; | ||
2776 | } | ||
2777 | |||
2778 | state = devm_kzalloc(&client->dev, sizeof(struct adv7842_state), GFP_KERNEL); | ||
2779 | if (!state) { | ||
2780 | v4l_err(client, "Could not allocate adv7842_state memory!\n"); | ||
2781 | return -ENOMEM; | ||
2782 | } | ||
2783 | |||
2784 | sd = &state->sd; | ||
2785 | v4l2_i2c_subdev_init(sd, client, &adv7842_ops); | ||
2786 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
2787 | state->connector_hdmi = pdata->connector_hdmi; | ||
2788 | state->mode = pdata->mode; | ||
2789 | |||
2790 | state->hdmi_port_a = true; | ||
2791 | |||
2792 | /* i2c access to adv7842? */ | ||
2793 | rev = adv_smbus_read_byte_data_check(client, 0xea, false) << 8 | | ||
2794 | adv_smbus_read_byte_data_check(client, 0xeb, false); | ||
2795 | if (rev != 0x2012) { | ||
2796 | v4l2_info(sd, "got rev=0x%04x on first read attempt\n", rev); | ||
2797 | rev = adv_smbus_read_byte_data_check(client, 0xea, false) << 8 | | ||
2798 | adv_smbus_read_byte_data_check(client, 0xeb, false); | ||
2799 | } | ||
2800 | if (rev != 0x2012) { | ||
2801 | v4l2_info(sd, "not an adv7842 on address 0x%x (rev=0x%04x)\n", | ||
2802 | client->addr << 1, rev); | ||
2803 | return -ENODEV; | ||
2804 | } | ||
2805 | |||
2806 | if (pdata->chip_reset) | ||
2807 | main_reset(sd); | ||
2808 | |||
2809 | /* control handlers */ | ||
2810 | hdl = &state->hdl; | ||
2811 | v4l2_ctrl_handler_init(hdl, 6); | ||
2812 | |||
2813 | /* add in ascending ID order */ | ||
2814 | v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, | ||
2815 | V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); | ||
2816 | v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, | ||
2817 | V4L2_CID_CONTRAST, 0, 255, 1, 128); | ||
2818 | v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, | ||
2819 | V4L2_CID_SATURATION, 0, 255, 1, 128); | ||
2820 | v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, | ||
2821 | V4L2_CID_HUE, 0, 128, 1, 0); | ||
2822 | |||
2823 | /* custom controls */ | ||
2824 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
2825 | V4L2_CID_DV_RX_POWER_PRESENT, 0, 3, 0, 0); | ||
2826 | state->analog_sampling_phase_ctrl = v4l2_ctrl_new_custom(hdl, | ||
2827 | &adv7842_ctrl_analog_sampling_phase, NULL); | ||
2828 | state->free_run_color_ctrl_manual = v4l2_ctrl_new_custom(hdl, | ||
2829 | &adv7842_ctrl_free_run_color_manual, NULL); | ||
2830 | state->free_run_color_ctrl = v4l2_ctrl_new_custom(hdl, | ||
2831 | &adv7842_ctrl_free_run_color, NULL); | ||
2832 | state->rgb_quantization_range_ctrl = | ||
2833 | v4l2_ctrl_new_std_menu(hdl, &adv7842_ctrl_ops, | ||
2834 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | ||
2835 | 0, V4L2_DV_RGB_RANGE_AUTO); | ||
2836 | sd->ctrl_handler = hdl; | ||
2837 | if (hdl->error) { | ||
2838 | err = hdl->error; | ||
2839 | goto err_hdl; | ||
2840 | } | ||
2841 | state->detect_tx_5v_ctrl->is_private = true; | ||
2842 | state->rgb_quantization_range_ctrl->is_private = true; | ||
2843 | state->analog_sampling_phase_ctrl->is_private = true; | ||
2844 | state->free_run_color_ctrl_manual->is_private = true; | ||
2845 | state->free_run_color_ctrl->is_private = true; | ||
2846 | |||
2847 | if (adv7842_s_detect_tx_5v_ctrl(sd)) { | ||
2848 | err = -ENODEV; | ||
2849 | goto err_hdl; | ||
2850 | } | ||
2851 | |||
2852 | state->i2c_avlink = adv7842_dummy_client(sd, pdata->i2c_avlink, 0xf3); | ||
2853 | state->i2c_cec = adv7842_dummy_client(sd, pdata->i2c_cec, 0xf4); | ||
2854 | state->i2c_infoframe = adv7842_dummy_client(sd, pdata->i2c_infoframe, 0xf5); | ||
2855 | state->i2c_sdp_io = adv7842_dummy_client(sd, pdata->i2c_sdp_io, 0xf2); | ||
2856 | state->i2c_sdp = adv7842_dummy_client(sd, pdata->i2c_sdp, 0xf1); | ||
2857 | state->i2c_afe = adv7842_dummy_client(sd, pdata->i2c_afe, 0xf8); | ||
2858 | state->i2c_repeater = adv7842_dummy_client(sd, pdata->i2c_repeater, 0xf9); | ||
2859 | state->i2c_edid = adv7842_dummy_client(sd, pdata->i2c_edid, 0xfa); | ||
2860 | state->i2c_hdmi = adv7842_dummy_client(sd, pdata->i2c_hdmi, 0xfb); | ||
2861 | state->i2c_cp = adv7842_dummy_client(sd, pdata->i2c_cp, 0xfd); | ||
2862 | state->i2c_vdp = adv7842_dummy_client(sd, pdata->i2c_vdp, 0xfe); | ||
2863 | if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe || | ||
2864 | !state->i2c_sdp_io || !state->i2c_sdp || !state->i2c_afe || | ||
2865 | !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi || | ||
2866 | !state->i2c_cp || !state->i2c_vdp) { | ||
2867 | err = -ENOMEM; | ||
2868 | v4l2_err(sd, "failed to create all i2c clients\n"); | ||
2869 | goto err_i2c; | ||
2870 | } | ||
2871 | |||
2872 | /* work queues */ | ||
2873 | state->work_queues = create_singlethread_workqueue(client->name); | ||
2874 | if (!state->work_queues) { | ||
2875 | v4l2_err(sd, "Could not create work queue\n"); | ||
2876 | err = -ENOMEM; | ||
2877 | goto err_i2c; | ||
2878 | } | ||
2879 | |||
2880 | INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, | ||
2881 | adv7842_delayed_work_enable_hotplug); | ||
2882 | |||
2883 | state->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
2884 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | ||
2885 | if (err) | ||
2886 | goto err_work_queues; | ||
2887 | |||
2888 | err = adv7842_core_init(sd, pdata); | ||
2889 | if (err) | ||
2890 | goto err_entity; | ||
2891 | |||
2892 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, | ||
2893 | client->addr << 1, client->adapter->name); | ||
2894 | return 0; | ||
2895 | |||
2896 | err_entity: | ||
2897 | media_entity_cleanup(&sd->entity); | ||
2898 | err_work_queues: | ||
2899 | cancel_delayed_work(&state->delayed_work_enable_hotplug); | ||
2900 | destroy_workqueue(state->work_queues); | ||
2901 | err_i2c: | ||
2902 | adv7842_unregister_clients(state); | ||
2903 | err_hdl: | ||
2904 | v4l2_ctrl_handler_free(hdl); | ||
2905 | return err; | ||
2906 | } | ||
2907 | |||
2908 | /* ----------------------------------------------------------------------- */ | ||
2909 | |||
2910 | static int adv7842_remove(struct i2c_client *client) | ||
2911 | { | ||
2912 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
2913 | struct adv7842_state *state = to_state(sd); | ||
2914 | |||
2915 | adv7842_irq_enable(sd, false); | ||
2916 | |||
2917 | cancel_delayed_work(&state->delayed_work_enable_hotplug); | ||
2918 | destroy_workqueue(state->work_queues); | ||
2919 | v4l2_device_unregister_subdev(sd); | ||
2920 | media_entity_cleanup(&sd->entity); | ||
2921 | adv7842_unregister_clients(to_state(sd)); | ||
2922 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
2923 | return 0; | ||
2924 | } | ||
2925 | |||
2926 | /* ----------------------------------------------------------------------- */ | ||
2927 | |||
2928 | static struct i2c_device_id adv7842_id[] = { | ||
2929 | { "adv7842", 0 }, | ||
2930 | { } | ||
2931 | }; | ||
2932 | MODULE_DEVICE_TABLE(i2c, adv7842_id); | ||
2933 | |||
2934 | /* ----------------------------------------------------------------------- */ | ||
2935 | |||
2936 | static struct i2c_driver adv7842_driver = { | ||
2937 | .driver = { | ||
2938 | .owner = THIS_MODULE, | ||
2939 | .name = "adv7842", | ||
2940 | }, | ||
2941 | .probe = adv7842_probe, | ||
2942 | .remove = adv7842_remove, | ||
2943 | .id_table = adv7842_id, | ||
2944 | }; | ||
2945 | |||
2946 | module_i2c_driver(adv7842_driver); | ||
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index a9857022f71d..a9110d8bbbcd 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c | |||
@@ -209,7 +209,8 @@ static int ml86v7667_mbus_fmt(struct v4l2_subdev *sd, | |||
209 | 209 | ||
210 | fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; | 210 | fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; |
211 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; | 211 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; |
212 | fmt->field = V4L2_FIELD_INTERLACED; | 212 | /* The top field is always transferred first by the chip */ |
213 | fmt->field = V4L2_FIELD_INTERLACED_TB; | ||
213 | fmt->width = 720; | 214 | fmt->width = 720; |
214 | fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576; | 215 | fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576; |
215 | 216 | ||
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 60c6f6739560..2c50effaa334 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
16 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
17 | #include <linux/log2.h> | 18 | #include <linux/log2.h> |
@@ -135,6 +136,8 @@ struct mt9v032 { | |||
135 | struct mutex power_lock; | 136 | struct mutex power_lock; |
136 | int power_count; | 137 | int power_count; |
137 | 138 | ||
139 | struct clk *clk; | ||
140 | |||
138 | struct mt9v032_platform_data *pdata; | 141 | struct mt9v032_platform_data *pdata; |
139 | 142 | ||
140 | u32 sysclk; | 143 | u32 sysclk; |
@@ -219,10 +222,9 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) | |||
219 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | 222 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); |
220 | int ret; | 223 | int ret; |
221 | 224 | ||
222 | if (mt9v032->pdata->set_clock) { | 225 | clk_set_rate(mt9v032->clk, mt9v032->sysclk); |
223 | mt9v032->pdata->set_clock(&mt9v032->subdev, mt9v032->sysclk); | 226 | clk_prepare_enable(mt9v032->clk); |
224 | udelay(1); | 227 | udelay(1); |
225 | } | ||
226 | 228 | ||
227 | /* Reset the chip and stop data read out */ | 229 | /* Reset the chip and stop data read out */ |
228 | ret = mt9v032_write(client, MT9V032_RESET, 1); | 230 | ret = mt9v032_write(client, MT9V032_RESET, 1); |
@@ -238,8 +240,7 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) | |||
238 | 240 | ||
239 | static void mt9v032_power_off(struct mt9v032 *mt9v032) | 241 | static void mt9v032_power_off(struct mt9v032 *mt9v032) |
240 | { | 242 | { |
241 | if (mt9v032->pdata->set_clock) | 243 | clk_disable_unprepare(mt9v032->clk); |
242 | mt9v032->pdata->set_clock(&mt9v032->subdev, 0); | ||
243 | } | 244 | } |
244 | 245 | ||
245 | static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) | 246 | static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) |
@@ -748,6 +749,10 @@ static int mt9v032_probe(struct i2c_client *client, | |||
748 | if (!mt9v032) | 749 | if (!mt9v032) |
749 | return -ENOMEM; | 750 | return -ENOMEM; |
750 | 751 | ||
752 | mt9v032->clk = devm_clk_get(&client->dev, NULL); | ||
753 | if (IS_ERR(mt9v032->clk)) | ||
754 | return PTR_ERR(mt9v032->clk); | ||
755 | |||
751 | mutex_init(&mt9v032->power_lock); | 756 | mutex_init(&mt9v032->power_lock); |
752 | mt9v032->pdata = pdata; | 757 | mt9v032->pdata = pdata; |
753 | 758 | ||
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 1dbb8118a285..4da90c621f7e 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c | |||
@@ -1083,7 +1083,7 @@ static int ov965x_enum_frame_sizes(struct v4l2_subdev *sd, | |||
1083 | { | 1083 | { |
1084 | int i = ARRAY_SIZE(ov965x_formats); | 1084 | int i = ARRAY_SIZE(ov965x_formats); |
1085 | 1085 | ||
1086 | if (fse->index > ARRAY_SIZE(ov965x_framesizes)) | 1086 | if (fse->index >= ARRAY_SIZE(ov965x_framesizes)) |
1087 | return -EINVAL; | 1087 | return -EINVAL; |
1088 | 1088 | ||
1089 | while (--i) | 1089 | while (--i) |
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 825ea86d982d..b76ec0e7e685 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c | |||
@@ -1111,6 +1111,11 @@ static int s5c73m3_oif_set_fmt(struct v4l2_subdev *sd, | |||
1111 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | 1111 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
1112 | mf = v4l2_subdev_get_try_format(fh, fmt->pad); | 1112 | mf = v4l2_subdev_get_try_format(fh, fmt->pad); |
1113 | *mf = fmt->format; | 1113 | *mf = fmt->format; |
1114 | if (fmt->pad == OIF_ISP_PAD) { | ||
1115 | mf = v4l2_subdev_get_try_format(fh, OIF_SOURCE_PAD); | ||
1116 | mf->width = fmt->format.width; | ||
1117 | mf->height = fmt->format.height; | ||
1118 | } | ||
1114 | } else { | 1119 | } else { |
1115 | switch (fmt->pad) { | 1120 | switch (fmt->pad) { |
1116 | case OIF_ISP_PAD: | 1121 | case OIF_ISP_PAD: |
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 789c02a6ca1a..629a5cdadd3a 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c | |||
@@ -1003,7 +1003,7 @@ static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd, | |||
1003 | const struct s5k6aa_interval *fi; | 1003 | const struct s5k6aa_interval *fi; |
1004 | int ret = 0; | 1004 | int ret = 0; |
1005 | 1005 | ||
1006 | if (fie->index > ARRAY_SIZE(s5k6aa_intervals)) | 1006 | if (fie->index >= ARRAY_SIZE(s5k6aa_intervals)) |
1007 | return -EINVAL; | 1007 | return -EINVAL; |
1008 | 1008 | ||
1009 | v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN, | 1009 | v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN, |
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 7fd766ec64c8..637d02634527 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c | |||
@@ -225,19 +225,63 @@ static const unsigned char saa7111_init[] = { | |||
225 | 0x00, 0x00 | 225 | 0x00, 0x00 |
226 | }; | 226 | }; |
227 | 227 | ||
228 | /* SAA7113/GM7113C init codes | 228 | /* |
229 | * It's important that R_14... R_17 == 0x00 | 229 | * This table has one illegal value, and some values that are not |
230 | * for the gm7113c chip to deliver stable video | 230 | * correct according to the datasheet initialization table. |
231 | * | ||
232 | * If you need a table with legal/default values tell the driver in | ||
233 | * i2c_board_info.platform_data, and you will get the gm7113c_init | ||
234 | * table instead. | ||
231 | */ | 235 | */ |
236 | |||
237 | /* SAA7113 Init codes */ | ||
232 | static const unsigned char saa7113_init[] = { | 238 | static const unsigned char saa7113_init[] = { |
233 | R_01_INC_DELAY, 0x08, | 239 | R_01_INC_DELAY, 0x08, |
234 | R_02_INPUT_CNTL_1, 0xc2, | 240 | R_02_INPUT_CNTL_1, 0xc2, |
235 | R_03_INPUT_CNTL_2, 0x30, | 241 | R_03_INPUT_CNTL_2, 0x30, |
236 | R_04_INPUT_CNTL_3, 0x00, | 242 | R_04_INPUT_CNTL_3, 0x00, |
237 | R_05_INPUT_CNTL_4, 0x00, | 243 | R_05_INPUT_CNTL_4, 0x00, |
238 | R_06_H_SYNC_START, 0x89, | 244 | R_06_H_SYNC_START, 0x89, /* Illegal value -119, |
245 | * min. value = -108 (0x94) */ | ||
246 | R_07_H_SYNC_STOP, 0x0d, | ||
247 | R_08_SYNC_CNTL, 0x88, /* Not datasheet default. | ||
248 | * HTC = VTR mode, should be 0x98 */ | ||
249 | R_09_LUMA_CNTL, 0x01, | ||
250 | R_0A_LUMA_BRIGHT_CNTL, 0x80, | ||
251 | R_0B_LUMA_CONTRAST_CNTL, 0x47, | ||
252 | R_0C_CHROMA_SAT_CNTL, 0x40, | ||
253 | R_0D_CHROMA_HUE_CNTL, 0x00, | ||
254 | R_0E_CHROMA_CNTL_1, 0x01, | ||
255 | R_0F_CHROMA_GAIN_CNTL, 0x2a, | ||
256 | R_10_CHROMA_CNTL_2, 0x08, /* Not datsheet default. | ||
257 | * VRLN enabled, should be 0x00 */ | ||
258 | R_11_MODE_DELAY_CNTL, 0x0c, | ||
259 | R_12_RT_SIGNAL_CNTL, 0x07, /* Not datasheet default, | ||
260 | * should be 0x01 */ | ||
261 | R_13_RT_X_PORT_OUT_CNTL, 0x00, | ||
262 | R_14_ANAL_ADC_COMPAT_CNTL, 0x00, | ||
263 | R_15_VGATE_START_FID_CHG, 0x00, | ||
264 | R_16_VGATE_STOP, 0x00, | ||
265 | R_17_MISC_VGATE_CONF_AND_MSB, 0x00, | ||
266 | |||
267 | 0x00, 0x00 | ||
268 | }; | ||
269 | |||
270 | /* | ||
271 | * GM7113C is a clone of the SAA7113 chip | ||
272 | * This init table is copied out of the saa7113 datasheet. | ||
273 | * In R_08 we enable "Automatic Field Detection" [AUFD], | ||
274 | * this is disabled when saa711x_set_v4lstd is called. | ||
275 | */ | ||
276 | static const unsigned char gm7113c_init[] = { | ||
277 | R_01_INC_DELAY, 0x08, | ||
278 | R_02_INPUT_CNTL_1, 0xc0, | ||
279 | R_03_INPUT_CNTL_2, 0x33, | ||
280 | R_04_INPUT_CNTL_3, 0x00, | ||
281 | R_05_INPUT_CNTL_4, 0x00, | ||
282 | R_06_H_SYNC_START, 0xe9, | ||
239 | R_07_H_SYNC_STOP, 0x0d, | 283 | R_07_H_SYNC_STOP, 0x0d, |
240 | R_08_SYNC_CNTL, 0x88, | 284 | R_08_SYNC_CNTL, 0x98, |
241 | R_09_LUMA_CNTL, 0x01, | 285 | R_09_LUMA_CNTL, 0x01, |
242 | R_0A_LUMA_BRIGHT_CNTL, 0x80, | 286 | R_0A_LUMA_BRIGHT_CNTL, 0x80, |
243 | R_0B_LUMA_CONTRAST_CNTL, 0x47, | 287 | R_0B_LUMA_CONTRAST_CNTL, 0x47, |
@@ -245,9 +289,9 @@ static const unsigned char saa7113_init[] = { | |||
245 | R_0D_CHROMA_HUE_CNTL, 0x00, | 289 | R_0D_CHROMA_HUE_CNTL, 0x00, |
246 | R_0E_CHROMA_CNTL_1, 0x01, | 290 | R_0E_CHROMA_CNTL_1, 0x01, |
247 | R_0F_CHROMA_GAIN_CNTL, 0x2a, | 291 | R_0F_CHROMA_GAIN_CNTL, 0x2a, |
248 | R_10_CHROMA_CNTL_2, 0x08, | 292 | R_10_CHROMA_CNTL_2, 0x00, |
249 | R_11_MODE_DELAY_CNTL, 0x0c, | 293 | R_11_MODE_DELAY_CNTL, 0x0c, |
250 | R_12_RT_SIGNAL_CNTL, 0x07, | 294 | R_12_RT_SIGNAL_CNTL, 0x01, |
251 | R_13_RT_X_PORT_OUT_CNTL, 0x00, | 295 | R_13_RT_X_PORT_OUT_CNTL, 0x00, |
252 | R_14_ANAL_ADC_COMPAT_CNTL, 0x00, | 296 | R_14_ANAL_ADC_COMPAT_CNTL, 0x00, |
253 | R_15_VGATE_START_FID_CHG, 0x00, | 297 | R_15_VGATE_START_FID_CHG, 0x00, |
@@ -462,24 +506,6 @@ static const unsigned char saa7115_cfg_50hz_video[] = { | |||
462 | 506 | ||
463 | /* ============== SAA7715 VIDEO templates (end) ======= */ | 507 | /* ============== SAA7715 VIDEO templates (end) ======= */ |
464 | 508 | ||
465 | /* ============== GM7113C VIDEO templates ============= */ | ||
466 | static const unsigned char gm7113c_cfg_60hz_video[] = { | ||
467 | R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */ | ||
468 | R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */ | ||
469 | |||
470 | 0x00, 0x00 | ||
471 | }; | ||
472 | |||
473 | static const unsigned char gm7113c_cfg_50hz_video[] = { | ||
474 | R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */ | ||
475 | R_0E_CHROMA_CNTL_1, 0x07, | ||
476 | |||
477 | 0x00, 0x00 | ||
478 | }; | ||
479 | |||
480 | /* ============== GM7113C VIDEO templates (end) ======= */ | ||
481 | |||
482 | |||
483 | static const unsigned char saa7115_cfg_vbi_on[] = { | 509 | static const unsigned char saa7115_cfg_vbi_on[] = { |
484 | R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */ | 510 | R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */ |
485 | R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */ | 511 | R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */ |
@@ -964,17 +990,24 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) | |||
964 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. | 990 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. |
965 | if (std & V4L2_STD_525_60) { | 991 | if (std & V4L2_STD_525_60) { |
966 | v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); | 992 | v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); |
967 | if (state->ident == GM7113C) | 993 | if (state->ident == GM7113C) { |
968 | saa711x_writeregs(sd, gm7113c_cfg_60hz_video); | 994 | u8 reg = saa711x_read(sd, R_08_SYNC_CNTL); |
969 | else | 995 | reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD); |
996 | reg |= SAA7113_R_08_FSEL; | ||
997 | saa711x_write(sd, R_08_SYNC_CNTL, reg); | ||
998 | } else { | ||
970 | saa711x_writeregs(sd, saa7115_cfg_60hz_video); | 999 | saa711x_writeregs(sd, saa7115_cfg_60hz_video); |
1000 | } | ||
971 | saa711x_set_size(sd, 720, 480); | 1001 | saa711x_set_size(sd, 720, 480); |
972 | } else { | 1002 | } else { |
973 | v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); | 1003 | v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); |
974 | if (state->ident == GM7113C) | 1004 | if (state->ident == GM7113C) { |
975 | saa711x_writeregs(sd, gm7113c_cfg_50hz_video); | 1005 | u8 reg = saa711x_read(sd, R_08_SYNC_CNTL); |
976 | else | 1006 | reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD); |
1007 | saa711x_write(sd, R_08_SYNC_CNTL, reg); | ||
1008 | } else { | ||
977 | saa711x_writeregs(sd, saa7115_cfg_50hz_video); | 1009 | saa711x_writeregs(sd, saa7115_cfg_50hz_video); |
1010 | } | ||
978 | saa711x_set_size(sd, 720, 576); | 1011 | saa711x_set_size(sd, 720, 576); |
979 | } | 1012 | } |
980 | 1013 | ||
@@ -1596,6 +1629,65 @@ static const struct v4l2_subdev_ops saa711x_ops = { | |||
1596 | 1629 | ||
1597 | /* ----------------------------------------------------------------------- */ | 1630 | /* ----------------------------------------------------------------------- */ |
1598 | 1631 | ||
1632 | static void saa711x_write_platform_data(struct saa711x_state *state, | ||
1633 | struct saa7115_platform_data *data) | ||
1634 | { | ||
1635 | struct v4l2_subdev *sd = &state->sd; | ||
1636 | u8 work; | ||
1637 | |||
1638 | if (state->ident != GM7113C && | ||
1639 | state->ident != SAA7113) | ||
1640 | return; | ||
1641 | |||
1642 | if (data->saa7113_r08_htc) { | ||
1643 | work = saa711x_read(sd, R_08_SYNC_CNTL); | ||
1644 | work &= ~SAA7113_R_08_HTC_MASK; | ||
1645 | work |= ((*data->saa7113_r08_htc) << SAA7113_R_08_HTC_OFFSET); | ||
1646 | saa711x_write(sd, R_08_SYNC_CNTL, work); | ||
1647 | } | ||
1648 | |||
1649 | if (data->saa7113_r10_vrln) { | ||
1650 | work = saa711x_read(sd, R_10_CHROMA_CNTL_2); | ||
1651 | work &= ~SAA7113_R_10_VRLN_MASK; | ||
1652 | if (*data->saa7113_r10_vrln) | ||
1653 | work |= (1 << SAA7113_R_10_VRLN_OFFSET); | ||
1654 | saa711x_write(sd, R_10_CHROMA_CNTL_2, work); | ||
1655 | } | ||
1656 | |||
1657 | if (data->saa7113_r10_ofts) { | ||
1658 | work = saa711x_read(sd, R_10_CHROMA_CNTL_2); | ||
1659 | work &= ~SAA7113_R_10_OFTS_MASK; | ||
1660 | work |= (*data->saa7113_r10_ofts << SAA7113_R_10_OFTS_OFFSET); | ||
1661 | saa711x_write(sd, R_10_CHROMA_CNTL_2, work); | ||
1662 | } | ||
1663 | |||
1664 | if (data->saa7113_r12_rts0) { | ||
1665 | work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL); | ||
1666 | work &= ~SAA7113_R_12_RTS0_MASK; | ||
1667 | work |= (*data->saa7113_r12_rts0 << SAA7113_R_12_RTS0_OFFSET); | ||
1668 | |||
1669 | /* According to the datasheet, | ||
1670 | * SAA7113_RTS_DOT_IN should only be used on RTS1 */ | ||
1671 | WARN_ON(*data->saa7113_r12_rts0 == SAA7113_RTS_DOT_IN); | ||
1672 | saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work); | ||
1673 | } | ||
1674 | |||
1675 | if (data->saa7113_r12_rts1) { | ||
1676 | work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL); | ||
1677 | work &= ~SAA7113_R_12_RTS1_MASK; | ||
1678 | work |= (*data->saa7113_r12_rts1 << SAA7113_R_12_RTS1_OFFSET); | ||
1679 | saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work); | ||
1680 | } | ||
1681 | |||
1682 | if (data->saa7113_r13_adlsb) { | ||
1683 | work = saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL); | ||
1684 | work &= ~SAA7113_R_13_ADLSB_MASK; | ||
1685 | if (*data->saa7113_r13_adlsb) | ||
1686 | work |= (1 << SAA7113_R_13_ADLSB_OFFSET); | ||
1687 | saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, work); | ||
1688 | } | ||
1689 | } | ||
1690 | |||
1599 | /** | 1691 | /** |
1600 | * saa711x_detect_chip - Detects the saa711x (or clone) variant | 1692 | * saa711x_detect_chip - Detects the saa711x (or clone) variant |
1601 | * @client: I2C client structure. | 1693 | * @client: I2C client structure. |
@@ -1704,6 +1796,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
1704 | struct saa711x_state *state; | 1796 | struct saa711x_state *state; |
1705 | struct v4l2_subdev *sd; | 1797 | struct v4l2_subdev *sd; |
1706 | struct v4l2_ctrl_handler *hdl; | 1798 | struct v4l2_ctrl_handler *hdl; |
1799 | struct saa7115_platform_data *pdata; | ||
1707 | int ident; | 1800 | int ident; |
1708 | char name[CHIP_VER_SIZE + 1]; | 1801 | char name[CHIP_VER_SIZE + 1]; |
1709 | 1802 | ||
@@ -1767,21 +1860,31 @@ static int saa711x_probe(struct i2c_client *client, | |||
1767 | 1860 | ||
1768 | /* init to 60hz/48khz */ | 1861 | /* init to 60hz/48khz */ |
1769 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; | 1862 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; |
1863 | pdata = client->dev.platform_data; | ||
1770 | switch (state->ident) { | 1864 | switch (state->ident) { |
1771 | case SAA7111: | 1865 | case SAA7111: |
1772 | case SAA7111A: | 1866 | case SAA7111A: |
1773 | saa711x_writeregs(sd, saa7111_init); | 1867 | saa711x_writeregs(sd, saa7111_init); |
1774 | break; | 1868 | break; |
1775 | case GM7113C: | 1869 | case GM7113C: |
1870 | saa711x_writeregs(sd, gm7113c_init); | ||
1871 | break; | ||
1776 | case SAA7113: | 1872 | case SAA7113: |
1777 | saa711x_writeregs(sd, saa7113_init); | 1873 | if (pdata && pdata->saa7113_force_gm7113c_init) |
1874 | saa711x_writeregs(sd, gm7113c_init); | ||
1875 | else | ||
1876 | saa711x_writeregs(sd, saa7113_init); | ||
1778 | break; | 1877 | break; |
1779 | default: | 1878 | default: |
1780 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; | 1879 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; |
1781 | saa711x_writeregs(sd, saa7115_init_auto_input); | 1880 | saa711x_writeregs(sd, saa7115_init_auto_input); |
1782 | } | 1881 | } |
1783 | if (state->ident > SAA7111A) | 1882 | if (state->ident > SAA7111A && state->ident != GM7113C) |
1784 | saa711x_writeregs(sd, saa7115_init_misc); | 1883 | saa711x_writeregs(sd, saa7115_init_misc); |
1884 | |||
1885 | if (pdata) | ||
1886 | saa711x_write_platform_data(state, pdata); | ||
1887 | |||
1785 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); | 1888 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); |
1786 | v4l2_ctrl_handler_setup(hdl); | 1889 | v4l2_ctrl_handler_setup(hdl); |
1787 | 1890 | ||
diff --git a/drivers/media/i2c/saa711x_regs.h b/drivers/media/i2c/saa711x_regs.h index 4e5f2eb0a2c1..730ca90b30ac 100644 --- a/drivers/media/i2c/saa711x_regs.h +++ b/drivers/media/i2c/saa711x_regs.h | |||
@@ -201,6 +201,25 @@ | |||
201 | #define R_FB_PULSE_C_POS_MSB 0xfb | 201 | #define R_FB_PULSE_C_POS_MSB 0xfb |
202 | #define R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES 0xff | 202 | #define R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES 0xff |
203 | 203 | ||
204 | /* SAA7113 bit-masks */ | ||
205 | #define SAA7113_R_08_HTC_OFFSET 3 | ||
206 | #define SAA7113_R_08_HTC_MASK (0x3 << SAA7113_R_08_HTC_OFFSET) | ||
207 | #define SAA7113_R_08_FSEL 0x40 | ||
208 | #define SAA7113_R_08_AUFD 0x80 | ||
209 | |||
210 | #define SAA7113_R_10_VRLN_OFFSET 3 | ||
211 | #define SAA7113_R_10_VRLN_MASK (0x1 << SAA7113_R_10_VRLN_OFFSET) | ||
212 | #define SAA7113_R_10_OFTS_OFFSET 6 | ||
213 | #define SAA7113_R_10_OFTS_MASK (0x3 << SAA7113_R_10_OFTS_OFFSET) | ||
214 | |||
215 | #define SAA7113_R_12_RTS0_OFFSET 0 | ||
216 | #define SAA7113_R_12_RTS0_MASK (0xf << SAA7113_R_12_RTS0_OFFSET) | ||
217 | #define SAA7113_R_12_RTS1_OFFSET 4 | ||
218 | #define SAA7113_R_12_RTS1_MASK (0xf << SAA7113_R_12_RTS1_OFFSET) | ||
219 | |||
220 | #define SAA7113_R_13_ADLSB_OFFSET 7 | ||
221 | #define SAA7113_R_13_ADLSB_MASK (0x1 << SAA7113_R_13_ADLSB_OFFSET) | ||
222 | |||
204 | #if 0 | 223 | #if 0 |
205 | /* Those structs will be used in the future for debug purposes */ | 224 | /* Those structs will be used in the future for debug purposes */ |
206 | struct saa711x_reg_descr { | 225 | struct saa711x_reg_descr { |
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c index d8d5da7c52db..2335529b195c 100644 --- a/drivers/media/i2c/smiapp-pll.c +++ b/drivers/media/i2c/smiapp-pll.c | |||
@@ -87,6 +87,17 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll) | |||
87 | dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz); | 87 | dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz); |
88 | } | 88 | } |
89 | 89 | ||
90 | /* | ||
91 | * Heuristically guess the PLL tree for a given common multiplier and | ||
92 | * divisor. Begin with the operational timing and continue to video | ||
93 | * timing once operational timing has been verified. | ||
94 | * | ||
95 | * @mul is the PLL multiplier and @div is the common divisor | ||
96 | * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL | ||
97 | * multiplier will be a multiple of @mul. | ||
98 | * | ||
99 | * @return Zero on success, error code on error. | ||
100 | */ | ||
90 | static int __smiapp_pll_calculate(struct device *dev, | 101 | static int __smiapp_pll_calculate(struct device *dev, |
91 | const struct smiapp_pll_limits *limits, | 102 | const struct smiapp_pll_limits *limits, |
92 | struct smiapp_pll *pll, uint32_t mul, | 103 | struct smiapp_pll *pll, uint32_t mul, |
@@ -95,6 +106,12 @@ static int __smiapp_pll_calculate(struct device *dev, | |||
95 | uint32_t sys_div; | 106 | uint32_t sys_div; |
96 | uint32_t best_pix_div = INT_MAX >> 1; | 107 | uint32_t best_pix_div = INT_MAX >> 1; |
97 | uint32_t vt_op_binning_div; | 108 | uint32_t vt_op_binning_div; |
109 | /* | ||
110 | * Higher multipliers (and divisors) are often required than | ||
111 | * necessitated by the external clock and the output clocks. | ||
112 | * There are limits for all values in the clock tree. These | ||
113 | * are the minimum and maximum multiplier for mul. | ||
114 | */ | ||
98 | uint32_t more_mul_min, more_mul_max; | 115 | uint32_t more_mul_min, more_mul_max; |
99 | uint32_t more_mul_factor; | 116 | uint32_t more_mul_factor; |
100 | uint32_t min_vt_div, max_vt_div, vt_div; | 117 | uint32_t min_vt_div, max_vt_div, vt_div; |
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 7ac7580f85c9..ae66d91bf713 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c | |||
@@ -1122,9 +1122,9 @@ static int smiapp_power_on(struct smiapp_sensor *sensor) | |||
1122 | rval = sensor->platform_data->set_xclk( | 1122 | rval = sensor->platform_data->set_xclk( |
1123 | &sensor->src->sd, sensor->platform_data->ext_clk); | 1123 | &sensor->src->sd, sensor->platform_data->ext_clk); |
1124 | else | 1124 | else |
1125 | rval = clk_enable(sensor->ext_clk); | 1125 | rval = clk_prepare_enable(sensor->ext_clk); |
1126 | if (rval < 0) { | 1126 | if (rval < 0) { |
1127 | dev_dbg(&client->dev, "failed to set xclk\n"); | 1127 | dev_dbg(&client->dev, "failed to enable xclk\n"); |
1128 | goto out_xclk_fail; | 1128 | goto out_xclk_fail; |
1129 | } | 1129 | } |
1130 | usleep_range(1000, 1000); | 1130 | usleep_range(1000, 1000); |
@@ -1244,7 +1244,7 @@ out_cci_addr_fail: | |||
1244 | if (sensor->platform_data->set_xclk) | 1244 | if (sensor->platform_data->set_xclk) |
1245 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); | 1245 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
1246 | else | 1246 | else |
1247 | clk_disable(sensor->ext_clk); | 1247 | clk_disable_unprepare(sensor->ext_clk); |
1248 | 1248 | ||
1249 | out_xclk_fail: | 1249 | out_xclk_fail: |
1250 | regulator_disable(sensor->vana); | 1250 | regulator_disable(sensor->vana); |
@@ -1270,7 +1270,7 @@ static void smiapp_power_off(struct smiapp_sensor *sensor) | |||
1270 | if (sensor->platform_data->set_xclk) | 1270 | if (sensor->platform_data->set_xclk) |
1271 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); | 1271 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
1272 | else | 1272 | else |
1273 | clk_disable(sensor->ext_clk); | 1273 | clk_disable_unprepare(sensor->ext_clk); |
1274 | usleep_range(5000, 5000); | 1274 | usleep_range(5000, 5000); |
1275 | regulator_disable(sensor->vana); | 1275 | regulator_disable(sensor->vana); |
1276 | sensor->streaming = 0; | 1276 | sensor->streaming = 0; |
@@ -1835,12 +1835,12 @@ static void smiapp_set_compose_scaler(struct v4l2_subdev *subdev, | |||
1835 | * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] | 1835 | * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] |
1836 | / sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE]; | 1836 | / sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE]; |
1837 | 1837 | ||
1838 | a = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX], | 1838 | a = clamp(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN], |
1839 | max(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN])); | 1839 | sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]); |
1840 | b = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX], | 1840 | b = clamp(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN], |
1841 | max(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN])); | 1841 | sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]); |
1842 | max_m = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX], | 1842 | max_m = clamp(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN], |
1843 | max(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN])); | 1843 | sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]); |
1844 | 1844 | ||
1845 | dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m); | 1845 | dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m); |
1846 | 1846 | ||
@@ -2363,11 +2363,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev) | |||
2363 | } | 2363 | } |
2364 | 2364 | ||
2365 | if (!sensor->platform_data->set_xclk) { | 2365 | if (!sensor->platform_data->set_xclk) { |
2366 | sensor->ext_clk = devm_clk_get(&client->dev, | 2366 | sensor->ext_clk = devm_clk_get(&client->dev, "ext_clk"); |
2367 | sensor->platform_data->ext_clk_name); | ||
2368 | if (IS_ERR(sensor->ext_clk)) { | 2367 | if (IS_ERR(sensor->ext_clk)) { |
2369 | dev_err(&client->dev, "could not get clock %s\n", | 2368 | dev_err(&client->dev, "could not get clock\n"); |
2370 | sensor->platform_data->ext_clk_name); | ||
2371 | return -ENODEV; | 2369 | return -ENODEV; |
2372 | } | 2370 | } |
2373 | 2371 | ||
@@ -2375,8 +2373,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev) | |||
2375 | sensor->platform_data->ext_clk); | 2373 | sensor->platform_data->ext_clk); |
2376 | if (rval < 0) { | 2374 | if (rval < 0) { |
2377 | dev_err(&client->dev, | 2375 | dev_err(&client->dev, |
2378 | "unable to set clock %s freq to %u\n", | 2376 | "unable to set clock freq to %u\n", |
2379 | sensor->platform_data->ext_clk_name, | ||
2380 | sensor->platform_data->ext_clk); | 2377 | sensor->platform_data->ext_clk); |
2381 | return -ENODEV; | 2378 | return -ENODEV; |
2382 | } | 2379 | } |
@@ -2839,7 +2836,7 @@ static int smiapp_remove(struct i2c_client *client) | |||
2839 | if (sensor->platform_data->set_xclk) | 2836 | if (sensor->platform_data->set_xclk) |
2840 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); | 2837 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
2841 | else | 2838 | else |
2842 | clk_disable(sensor->ext_clk); | 2839 | clk_disable_unprepare(sensor->ext_clk); |
2843 | sensor->power_count = 0; | 2840 | sensor->power_count = 0; |
2844 | } | 2841 | } |
2845 | 2842 | ||
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c index de3605df47c5..6f4056668bbc 100644 --- a/drivers/media/i2c/soc_camera/mt9m111.c +++ b/drivers/media/i2c/soc_camera/mt9m111.c | |||
@@ -946,6 +946,10 @@ static int mt9m111_probe(struct i2c_client *client, | |||
946 | if (!mt9m111) | 946 | if (!mt9m111) |
947 | return -ENOMEM; | 947 | return -ENOMEM; |
948 | 948 | ||
949 | mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
950 | if (IS_ERR(mt9m111->clk)) | ||
951 | return -EPROBE_DEFER; | ||
952 | |||
949 | /* Default HIGHPOWER context */ | 953 | /* Default HIGHPOWER context */ |
950 | mt9m111->ctx = &context_b; | 954 | mt9m111->ctx = &context_b; |
951 | 955 | ||
@@ -963,8 +967,10 @@ static int mt9m111_probe(struct i2c_client *client, | |||
963 | &mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0, | 967 | &mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0, |
964 | V4L2_EXPOSURE_AUTO); | 968 | V4L2_EXPOSURE_AUTO); |
965 | mt9m111->subdev.ctrl_handler = &mt9m111->hdl; | 969 | mt9m111->subdev.ctrl_handler = &mt9m111->hdl; |
966 | if (mt9m111->hdl.error) | 970 | if (mt9m111->hdl.error) { |
967 | return mt9m111->hdl.error; | 971 | ret = mt9m111->hdl.error; |
972 | goto out_clkput; | ||
973 | } | ||
968 | 974 | ||
969 | /* Second stage probe - when a capture adapter is there */ | 975 | /* Second stage probe - when a capture adapter is there */ |
970 | mt9m111->rect.left = MT9M111_MIN_DARK_COLS; | 976 | mt9m111->rect.left = MT9M111_MIN_DARK_COLS; |
@@ -975,18 +981,25 @@ static int mt9m111_probe(struct i2c_client *client, | |||
975 | mt9m111->lastpage = -1; | 981 | mt9m111->lastpage = -1; |
976 | mutex_init(&mt9m111->power_lock); | 982 | mutex_init(&mt9m111->power_lock); |
977 | 983 | ||
978 | mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); | 984 | ret = soc_camera_power_init(&client->dev, ssdd); |
979 | if (IS_ERR(mt9m111->clk)) { | 985 | if (ret < 0) |
980 | ret = PTR_ERR(mt9m111->clk); | 986 | goto out_hdlfree; |
981 | goto eclkget; | ||
982 | } | ||
983 | 987 | ||
984 | ret = mt9m111_video_probe(client); | 988 | ret = mt9m111_video_probe(client); |
985 | if (ret) { | 989 | if (ret < 0) |
986 | v4l2_clk_put(mt9m111->clk); | 990 | goto out_hdlfree; |
987 | eclkget: | 991 | |
988 | v4l2_ctrl_handler_free(&mt9m111->hdl); | 992 | mt9m111->subdev.dev = &client->dev; |
989 | } | 993 | ret = v4l2_async_register_subdev(&mt9m111->subdev); |
994 | if (ret < 0) | ||
995 | goto out_hdlfree; | ||
996 | |||
997 | return 0; | ||
998 | |||
999 | out_hdlfree: | ||
1000 | v4l2_ctrl_handler_free(&mt9m111->hdl); | ||
1001 | out_clkput: | ||
1002 | v4l2_clk_put(mt9m111->clk); | ||
990 | 1003 | ||
991 | return ret; | 1004 | return ret; |
992 | } | 1005 | } |
@@ -995,6 +1008,7 @@ static int mt9m111_remove(struct i2c_client *client) | |||
995 | { | 1008 | { |
996 | struct mt9m111 *mt9m111 = to_mt9m111(client); | 1009 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
997 | 1010 | ||
1011 | v4l2_async_unregister_subdev(&mt9m111->subdev); | ||
998 | v4l2_clk_put(mt9m111->clk); | 1012 | v4l2_clk_put(mt9m111->clk); |
999 | v4l2_device_unregister_subdev(&mt9m111->subdev); | 1013 | v4l2_device_unregister_subdev(&mt9m111->subdev); |
1000 | v4l2_ctrl_handler_free(&mt9m111->hdl); | 1014 | v4l2_ctrl_handler_free(&mt9m111->hdl); |
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 47d18d0bafe7..ee7bb0ffcecb 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c | |||
@@ -594,9 +594,12 @@ static int mt9t031_s_power(struct v4l2_subdev *sd, int on) | |||
594 | ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk); | 594 | ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk); |
595 | if (ret < 0) | 595 | if (ret < 0) |
596 | return ret; | 596 | return ret; |
597 | vdev->dev.type = &mt9t031_dev_type; | 597 | if (vdev) |
598 | /* Not needed during probing, when vdev isn't available yet */ | ||
599 | vdev->dev.type = &mt9t031_dev_type; | ||
598 | } else { | 600 | } else { |
599 | vdev->dev.type = NULL; | 601 | if (vdev) |
602 | vdev->dev.type = NULL; | ||
600 | soc_camera_power_off(&client->dev, ssdd, mt9t031->clk); | 603 | soc_camera_power_off(&client->dev, ssdd, mt9t031->clk); |
601 | } | 604 | } |
602 | 605 | ||
diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 0a2dacbd7a63..42276d93624c 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c | |||
@@ -291,10 +291,8 @@ static int ths7303_log_status(struct v4l2_subdev *sd) | |||
291 | struct v4l2_bt_timings *bt = bt = &state->bt; | 291 | struct v4l2_bt_timings *bt = bt = &state->bt; |
292 | u32 frame_width, frame_height; | 292 | u32 frame_width, frame_height; |
293 | 293 | ||
294 | frame_width = bt->width + bt->hfrontporch + | 294 | frame_width = V4L2_DV_BT_FRAME_WIDTH(bt); |
295 | bt->hsync + bt->hbackporch; | 295 | frame_height = V4L2_DV_BT_FRAME_HEIGHT(bt); |
296 | frame_height = bt->height + bt->vfrontporch + | ||
297 | bt->vsync + bt->vbackporch; | ||
298 | v4l2_info(sd, | 296 | v4l2_info(sd, |
299 | "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n", | 297 | "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n", |
300 | bt->width, bt->height, bt->interlaced ? "i" : "p", | 298 | bt->width, bt->height, bt->interlaced ? "i" : "p", |
diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index a24f90c5261c..a58a8f663ffb 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/v4l2-dv-timings.h> | 22 | #include <linux/v4l2-dv-timings.h> |
23 | 23 | ||
24 | #include <media/v4l2-dv-timings.h> | ||
25 | #include <media/v4l2-async.h> | ||
24 | #include <media/v4l2-device.h> | 26 | #include <media/v4l2-device.h> |
25 | 27 | ||
26 | #include "ths8200_regs.h" | 28 | #include "ths8200_regs.h" |
@@ -42,18 +44,16 @@ struct ths8200_state { | |||
42 | struct v4l2_dv_timings dv_timings; | 44 | struct v4l2_dv_timings dv_timings; |
43 | }; | 45 | }; |
44 | 46 | ||
45 | static const struct v4l2_dv_timings ths8200_timings[] = { | 47 | static const struct v4l2_dv_timings_cap ths8200_timings_cap = { |
46 | V4L2_DV_BT_CEA_720X480P59_94, | 48 | .type = V4L2_DV_BT_656_1120, |
47 | V4L2_DV_BT_CEA_1280X720P24, | 49 | .bt = { |
48 | V4L2_DV_BT_CEA_1280X720P25, | 50 | .max_width = 1920, |
49 | V4L2_DV_BT_CEA_1280X720P30, | 51 | .max_height = 1080, |
50 | V4L2_DV_BT_CEA_1280X720P50, | 52 | .min_pixelclock = 25000000, |
51 | V4L2_DV_BT_CEA_1280X720P60, | 53 | .max_pixelclock = 148500000, |
52 | V4L2_DV_BT_CEA_1920X1080P24, | 54 | .standards = V4L2_DV_BT_STD_CEA861, |
53 | V4L2_DV_BT_CEA_1920X1080P25, | 55 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE, |
54 | V4L2_DV_BT_CEA_1920X1080P30, | 56 | }, |
55 | V4L2_DV_BT_CEA_1920X1080P50, | ||
56 | V4L2_DV_BT_CEA_1920X1080P60, | ||
57 | }; | 57 | }; |
58 | 58 | ||
59 | static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) | 59 | static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) |
@@ -63,22 +63,22 @@ static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) | |||
63 | 63 | ||
64 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) | 64 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) |
65 | { | 65 | { |
66 | return t->hfrontporch + t->hsync + t->hbackporch; | 66 | return V4L2_DV_BT_BLANKING_WIDTH(t); |
67 | } | 67 | } |
68 | 68 | ||
69 | static inline unsigned htotal(const struct v4l2_bt_timings *t) | 69 | static inline unsigned htotal(const struct v4l2_bt_timings *t) |
70 | { | 70 | { |
71 | return t->width + t->hfrontporch + t->hsync + t->hbackporch; | 71 | return V4L2_DV_BT_FRAME_WIDTH(t); |
72 | } | 72 | } |
73 | 73 | ||
74 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) | 74 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) |
75 | { | 75 | { |
76 | return t->vfrontporch + t->vsync + t->vbackporch; | 76 | return V4L2_DV_BT_BLANKING_HEIGHT(t); |
77 | } | 77 | } |
78 | 78 | ||
79 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) | 79 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) |
80 | { | 80 | { |
81 | return t->height + t->vfrontporch + t->vsync + t->vbackporch; | 81 | return V4L2_DV_BT_FRAME_HEIGHT(t); |
82 | } | 82 | } |
83 | 83 | ||
84 | static int ths8200_read(struct v4l2_subdev *sd, u8 reg) | 84 | static int ths8200_read(struct v4l2_subdev *sd, u8 reg) |
@@ -133,39 +133,6 @@ static int ths8200_s_register(struct v4l2_subdev *sd, | |||
133 | } | 133 | } |
134 | #endif | 134 | #endif |
135 | 135 | ||
136 | static void ths8200_print_timings(struct v4l2_subdev *sd, | ||
137 | struct v4l2_dv_timings *timings, | ||
138 | const char *txt, bool detailed) | ||
139 | { | ||
140 | struct v4l2_bt_timings *bt = &timings->bt; | ||
141 | u32 htot, vtot; | ||
142 | |||
143 | if (timings->type != V4L2_DV_BT_656_1120) | ||
144 | return; | ||
145 | |||
146 | htot = htotal(bt); | ||
147 | vtot = vtotal(bt); | ||
148 | |||
149 | v4l2_info(sd, "%s %dx%d%s%d (%dx%d)", | ||
150 | txt, bt->width, bt->height, bt->interlaced ? "i" : "p", | ||
151 | (htot * vtot) > 0 ? ((u32)bt->pixelclock / (htot * vtot)) : 0, | ||
152 | htot, vtot); | ||
153 | |||
154 | if (detailed) { | ||
155 | v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n", | ||
156 | bt->hfrontporch, | ||
157 | (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", | ||
158 | bt->hsync, bt->hbackporch); | ||
159 | v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n", | ||
160 | bt->vfrontporch, | ||
161 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", | ||
162 | bt->vsync, bt->vbackporch); | ||
163 | v4l2_info(sd, | ||
164 | " pixelclock: %lld, flags: 0x%x, standards: 0x%x\n", | ||
165 | bt->pixelclock, bt->flags, bt->standards); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | static int ths8200_log_status(struct v4l2_subdev *sd) | 136 | static int ths8200_log_status(struct v4l2_subdev *sd) |
170 | { | 137 | { |
171 | struct ths8200_state *state = to_state(sd); | 138 | struct ths8200_state *state = to_state(sd); |
@@ -182,9 +149,8 @@ static int ths8200_log_status(struct v4l2_subdev *sd) | |||
182 | ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_LSB), | 149 | ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_LSB), |
183 | (ths8200_read(sd, THS8200_DTG2_LINE_CNT_MSB) & 0x07) * 256 + | 150 | (ths8200_read(sd, THS8200_DTG2_LINE_CNT_MSB) & 0x07) * 256 + |
184 | ths8200_read(sd, THS8200_DTG2_LINE_CNT_LSB)); | 151 | ths8200_read(sd, THS8200_DTG2_LINE_CNT_LSB)); |
185 | ths8200_print_timings(sd, &state->dv_timings, | 152 | v4l2_print_dv_timings(sd->name, "Configured format:", |
186 | "Configured format:", true); | 153 | &state->dv_timings, true); |
187 | |||
188 | return 0; | 154 | return 0; |
189 | } | 155 | } |
190 | 156 | ||
@@ -409,25 +375,15 @@ static int ths8200_s_dv_timings(struct v4l2_subdev *sd, | |||
409 | struct v4l2_dv_timings *timings) | 375 | struct v4l2_dv_timings *timings) |
410 | { | 376 | { |
411 | struct ths8200_state *state = to_state(sd); | 377 | struct ths8200_state *state = to_state(sd); |
412 | int i; | ||
413 | 378 | ||
414 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | 379 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); |
415 | 380 | ||
416 | if (timings->type != V4L2_DV_BT_656_1120) | 381 | if (!v4l2_valid_dv_timings(timings, &ths8200_timings_cap, |
417 | return -EINVAL; | 382 | NULL, NULL)) |
418 | |||
419 | /* TODO Support interlaced formats */ | ||
420 | if (timings->bt.interlaced) { | ||
421 | v4l2_dbg(1, debug, sd, "TODO Support interlaced formats\n"); | ||
422 | return -EINVAL; | 383 | return -EINVAL; |
423 | } | ||
424 | |||
425 | for (i = 0; i < ARRAY_SIZE(ths8200_timings); i++) { | ||
426 | if (v4l_match_dv_timings(&ths8200_timings[i], timings, 10)) | ||
427 | break; | ||
428 | } | ||
429 | 384 | ||
430 | if (i == ARRAY_SIZE(ths8200_timings)) { | 385 | if (!v4l2_find_dv_timings_cap(timings, &ths8200_timings_cap, 10, |
386 | NULL, NULL)) { | ||
431 | v4l2_dbg(1, debug, sd, "Unsupported format\n"); | 387 | v4l2_dbg(1, debug, sd, "Unsupported format\n"); |
432 | return -EINVAL; | 388 | return -EINVAL; |
433 | } | 389 | } |
@@ -457,26 +413,14 @@ static int ths8200_g_dv_timings(struct v4l2_subdev *sd, | |||
457 | static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, | 413 | static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, |
458 | struct v4l2_enum_dv_timings *timings) | 414 | struct v4l2_enum_dv_timings *timings) |
459 | { | 415 | { |
460 | /* Check requested format index is within range */ | 416 | return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap, |
461 | if (timings->index >= ARRAY_SIZE(ths8200_timings)) | 417 | NULL, NULL); |
462 | return -EINVAL; | ||
463 | |||
464 | timings->timings = ths8200_timings[timings->index]; | ||
465 | |||
466 | return 0; | ||
467 | } | 418 | } |
468 | 419 | ||
469 | static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, | 420 | static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, |
470 | struct v4l2_dv_timings_cap *cap) | 421 | struct v4l2_dv_timings_cap *cap) |
471 | { | 422 | { |
472 | cap->type = V4L2_DV_BT_656_1120; | 423 | *cap = ths8200_timings_cap; |
473 | cap->bt.max_width = 1920; | ||
474 | cap->bt.max_height = 1080; | ||
475 | cap->bt.min_pixelclock = 27000000; | ||
476 | cap->bt.max_pixelclock = 148500000; | ||
477 | cap->bt.standards = V4L2_DV_BT_STD_CEA861; | ||
478 | cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE; | ||
479 | |||
480 | return 0; | 424 | return 0; |
481 | } | 425 | } |
482 | 426 | ||
@@ -500,6 +444,7 @@ static int ths8200_probe(struct i2c_client *client, | |||
500 | { | 444 | { |
501 | struct ths8200_state *state; | 445 | struct ths8200_state *state; |
502 | struct v4l2_subdev *sd; | 446 | struct v4l2_subdev *sd; |
447 | int error; | ||
503 | 448 | ||
504 | /* Check if the adapter supports the needed features */ | 449 | /* Check if the adapter supports the needed features */ |
505 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 450 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
@@ -517,6 +462,10 @@ static int ths8200_probe(struct i2c_client *client, | |||
517 | 462 | ||
518 | ths8200_core_init(sd); | 463 | ths8200_core_init(sd); |
519 | 464 | ||
465 | error = v4l2_async_register_subdev(&state->sd); | ||
466 | if (error) | ||
467 | return error; | ||
468 | |||
520 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, | 469 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, |
521 | client->addr << 1, client->adapter->name); | 470 | client->addr << 1, client->adapter->name); |
522 | 471 | ||
@@ -526,12 +475,13 @@ static int ths8200_probe(struct i2c_client *client, | |||
526 | static int ths8200_remove(struct i2c_client *client) | 475 | static int ths8200_remove(struct i2c_client *client) |
527 | { | 476 | { |
528 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 477 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
478 | struct ths8200_state *decoder = to_state(sd); | ||
529 | 479 | ||
530 | v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, | 480 | v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, |
531 | client->addr << 1, client->adapter->name); | 481 | client->addr << 1, client->adapter->name); |
532 | 482 | ||
533 | ths8200_s_power(sd, false); | 483 | ths8200_s_power(sd, false); |
534 | 484 | v4l2_async_unregister_subdev(&decoder->sd); | |
535 | v4l2_device_unregister_subdev(sd); | 485 | v4l2_device_unregister_subdev(sd); |
536 | 486 | ||
537 | return 0; | 487 | return 0; |
@@ -543,10 +493,19 @@ static struct i2c_device_id ths8200_id[] = { | |||
543 | }; | 493 | }; |
544 | MODULE_DEVICE_TABLE(i2c, ths8200_id); | 494 | MODULE_DEVICE_TABLE(i2c, ths8200_id); |
545 | 495 | ||
496 | #if IS_ENABLED(CONFIG_OF) | ||
497 | static const struct of_device_id ths8200_of_match[] = { | ||
498 | { .compatible = "ti,ths8200", }, | ||
499 | { /* sentinel */ }, | ||
500 | }; | ||
501 | MODULE_DEVICE_TABLE(of, ths8200_of_match); | ||
502 | #endif | ||
503 | |||
546 | static struct i2c_driver ths8200_driver = { | 504 | static struct i2c_driver ths8200_driver = { |
547 | .driver = { | 505 | .driver = { |
548 | .owner = THIS_MODULE, | 506 | .owner = THIS_MODULE, |
549 | .name = "ths8200", | 507 | .name = "ths8200", |
508 | .of_match_table = of_match_ptr(ths8200_of_match), | ||
550 | }, | 509 | }, |
551 | .probe = ths8200_probe, | 510 | .probe = ths8200_probe, |
552 | .remove = ths8200_remove, | 511 | .remove = ths8200_remove, |
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 9c6d66a9868f..91f3dd4cda1b 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/v4l2-mediabus.h> | 37 | #include <linux/v4l2-mediabus.h> |
38 | 38 | ||
39 | #include <media/v4l2-async.h> | ||
39 | #include <media/v4l2-device.h> | 40 | #include <media/v4l2-device.h> |
40 | #include <media/v4l2-common.h> | 41 | #include <media/v4l2-common.h> |
41 | #include <media/v4l2-mediabus.h> | 42 | #include <media/v4l2-mediabus.h> |
@@ -1175,16 +1176,22 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1175 | sd->ctrl_handler = &decoder->hdl; | 1176 | sd->ctrl_handler = &decoder->hdl; |
1176 | if (decoder->hdl.error) { | 1177 | if (decoder->hdl.error) { |
1177 | ret = decoder->hdl.error; | 1178 | ret = decoder->hdl.error; |
1178 | 1179 | goto done; | |
1179 | v4l2_ctrl_handler_free(&decoder->hdl); | ||
1180 | return ret; | ||
1181 | } | 1180 | } |
1182 | v4l2_ctrl_handler_setup(&decoder->hdl); | 1181 | v4l2_ctrl_handler_setup(&decoder->hdl); |
1183 | 1182 | ||
1184 | v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); | 1183 | ret = v4l2_async_register_subdev(&decoder->sd); |
1185 | 1184 | if (!ret) | |
1186 | return 0; | 1185 | v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); |
1187 | 1186 | ||
1187 | done: | ||
1188 | if (ret < 0) { | ||
1189 | v4l2_ctrl_handler_free(&decoder->hdl); | ||
1190 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
1191 | media_entity_cleanup(&decoder->sd.entity); | ||
1192 | #endif | ||
1193 | } | ||
1194 | return ret; | ||
1188 | } | 1195 | } |
1189 | 1196 | ||
1190 | /** | 1197 | /** |
@@ -1199,6 +1206,7 @@ static int tvp514x_remove(struct i2c_client *client) | |||
1199 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 1206 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1200 | struct tvp514x_decoder *decoder = to_decoder(sd); | 1207 | struct tvp514x_decoder *decoder = to_decoder(sd); |
1201 | 1208 | ||
1209 | v4l2_async_unregister_subdev(&decoder->sd); | ||
1202 | v4l2_device_unregister_subdev(sd); | 1210 | v4l2_device_unregister_subdev(sd); |
1203 | #if defined(CONFIG_MEDIA_CONTROLLER) | 1211 | #if defined(CONFIG_MEDIA_CONTROLLER) |
1204 | media_entity_cleanup(&decoder->sd.entity); | 1212 | media_entity_cleanup(&decoder->sd.entity); |
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index a4e49483de6a..24a08fa7e328 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c | |||
@@ -31,9 +31,12 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/v4l2-dv-timings.h> | 32 | #include <linux/v4l2-dv-timings.h> |
33 | #include <media/tvp7002.h> | 33 | #include <media/tvp7002.h> |
34 | #include <media/v4l2-async.h> | ||
34 | #include <media/v4l2-device.h> | 35 | #include <media/v4l2-device.h> |
35 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
36 | #include <media/v4l2-ctrls.h> | 37 | #include <media/v4l2-ctrls.h> |
38 | #include <media/v4l2-of.h> | ||
39 | |||
37 | #include "tvp7002_reg.h" | 40 | #include "tvp7002_reg.h" |
38 | 41 | ||
39 | MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver"); | 42 | MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver"); |
@@ -942,6 +945,48 @@ static const struct v4l2_subdev_ops tvp7002_ops = { | |||
942 | .pad = &tvp7002_pad_ops, | 945 | .pad = &tvp7002_pad_ops, |
943 | }; | 946 | }; |
944 | 947 | ||
948 | static struct tvp7002_config * | ||
949 | tvp7002_get_pdata(struct i2c_client *client) | ||
950 | { | ||
951 | struct v4l2_of_endpoint bus_cfg; | ||
952 | struct tvp7002_config *pdata; | ||
953 | struct device_node *endpoint; | ||
954 | unsigned int flags; | ||
955 | |||
956 | if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) | ||
957 | return client->dev.platform_data; | ||
958 | |||
959 | endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); | ||
960 | if (!endpoint) | ||
961 | return NULL; | ||
962 | |||
963 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); | ||
964 | if (!pdata) | ||
965 | goto done; | ||
966 | |||
967 | v4l2_of_parse_endpoint(endpoint, &bus_cfg); | ||
968 | flags = bus_cfg.bus.parallel.flags; | ||
969 | |||
970 | if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) | ||
971 | pdata->hs_polarity = 1; | ||
972 | |||
973 | if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) | ||
974 | pdata->vs_polarity = 1; | ||
975 | |||
976 | if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) | ||
977 | pdata->clk_polarity = 1; | ||
978 | |||
979 | if (flags & V4L2_MBUS_FIELD_EVEN_HIGH) | ||
980 | pdata->fid_polarity = 1; | ||
981 | |||
982 | if (flags & V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH) | ||
983 | pdata->sog_polarity = 1; | ||
984 | |||
985 | done: | ||
986 | of_node_put(endpoint); | ||
987 | return pdata; | ||
988 | } | ||
989 | |||
945 | /* | 990 | /* |
946 | * tvp7002_probe - Probe a TVP7002 device | 991 | * tvp7002_probe - Probe a TVP7002 device |
947 | * @c: ptr to i2c_client struct | 992 | * @c: ptr to i2c_client struct |
@@ -953,32 +998,32 @@ static const struct v4l2_subdev_ops tvp7002_ops = { | |||
953 | */ | 998 | */ |
954 | static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) | 999 | static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) |
955 | { | 1000 | { |
1001 | struct tvp7002_config *pdata = tvp7002_get_pdata(c); | ||
956 | struct v4l2_subdev *sd; | 1002 | struct v4l2_subdev *sd; |
957 | struct tvp7002 *device; | 1003 | struct tvp7002 *device; |
958 | struct v4l2_dv_timings timings; | 1004 | struct v4l2_dv_timings timings; |
959 | int polarity_a; | 1005 | int polarity_a; |
960 | int polarity_b; | 1006 | int polarity_b; |
961 | u8 revision; | 1007 | u8 revision; |
962 | |||
963 | int error; | 1008 | int error; |
964 | 1009 | ||
1010 | if (pdata == NULL) { | ||
1011 | dev_err(&c->dev, "No platform data\n"); | ||
1012 | return -EINVAL; | ||
1013 | } | ||
1014 | |||
965 | /* Check if the adapter supports the needed features */ | 1015 | /* Check if the adapter supports the needed features */ |
966 | if (!i2c_check_functionality(c->adapter, | 1016 | if (!i2c_check_functionality(c->adapter, |
967 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | 1017 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
968 | return -EIO; | 1018 | return -EIO; |
969 | 1019 | ||
970 | if (!c->dev.platform_data) { | ||
971 | v4l_err(c, "No platform data!!\n"); | ||
972 | return -ENODEV; | ||
973 | } | ||
974 | |||
975 | device = devm_kzalloc(&c->dev, sizeof(struct tvp7002), GFP_KERNEL); | 1020 | device = devm_kzalloc(&c->dev, sizeof(struct tvp7002), GFP_KERNEL); |
976 | 1021 | ||
977 | if (!device) | 1022 | if (!device) |
978 | return -ENOMEM; | 1023 | return -ENOMEM; |
979 | 1024 | ||
980 | sd = &device->sd; | 1025 | sd = &device->sd; |
981 | device->pdata = c->dev.platform_data; | 1026 | device->pdata = pdata; |
982 | device->current_timings = tvp7002_timings; | 1027 | device->current_timings = tvp7002_timings; |
983 | 1028 | ||
984 | /* Tell v4l2 the device is ready */ | 1029 | /* Tell v4l2 the device is ready */ |
@@ -1039,6 +1084,10 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) | |||
1039 | } | 1084 | } |
1040 | v4l2_ctrl_handler_setup(&device->hdl); | 1085 | v4l2_ctrl_handler_setup(&device->hdl); |
1041 | 1086 | ||
1087 | error = v4l2_async_register_subdev(&device->sd); | ||
1088 | if (error) | ||
1089 | goto error; | ||
1090 | |||
1042 | return 0; | 1091 | return 0; |
1043 | 1092 | ||
1044 | error: | 1093 | error: |
@@ -1063,6 +1112,7 @@ static int tvp7002_remove(struct i2c_client *c) | |||
1063 | 1112 | ||
1064 | v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter" | 1113 | v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter" |
1065 | "on address 0x%x\n", c->addr); | 1114 | "on address 0x%x\n", c->addr); |
1115 | v4l2_async_unregister_subdev(&device->sd); | ||
1066 | #if defined(CONFIG_MEDIA_CONTROLLER) | 1116 | #if defined(CONFIG_MEDIA_CONTROLLER) |
1067 | media_entity_cleanup(&device->sd.entity); | 1117 | media_entity_cleanup(&device->sd.entity); |
1068 | #endif | 1118 | #endif |
@@ -1078,9 +1128,18 @@ static const struct i2c_device_id tvp7002_id[] = { | |||
1078 | }; | 1128 | }; |
1079 | MODULE_DEVICE_TABLE(i2c, tvp7002_id); | 1129 | MODULE_DEVICE_TABLE(i2c, tvp7002_id); |
1080 | 1130 | ||
1131 | #if IS_ENABLED(CONFIG_OF) | ||
1132 | static const struct of_device_id tvp7002_of_match[] = { | ||
1133 | { .compatible = "ti,tvp7002", }, | ||
1134 | { /* sentinel */ }, | ||
1135 | }; | ||
1136 | MODULE_DEVICE_TABLE(of, tvp7002_of_match); | ||
1137 | #endif | ||
1138 | |||
1081 | /* I2C driver data */ | 1139 | /* I2C driver data */ |
1082 | static struct i2c_driver tvp7002_driver = { | 1140 | static struct i2c_driver tvp7002_driver = { |
1083 | .driver = { | 1141 | .driver = { |
1142 | .of_match_table = of_match_ptr(tvp7002_of_match), | ||
1084 | .owner = THIS_MODULE, | 1143 | .owner = THIS_MODULE, |
1085 | .name = TVP7002_MODULE_NAME, | 1144 | .name = TVP7002_MODULE_NAME, |
1086 | }, | 1145 | }, |
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index cb30ffbd5ba8..2c286c307145 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c | |||
@@ -20,6 +20,7 @@ | |||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/bitmap.h> | ||
23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
25 | #include <media/media-entity.h> | 26 | #include <media/media-entity.h> |
@@ -121,7 +122,6 @@ static struct media_entity *stack_pop(struct media_entity_graph *graph) | |||
121 | return entity; | 122 | return entity; |
122 | } | 123 | } |
123 | 124 | ||
124 | #define stack_peek(en) ((en)->stack[(en)->top - 1].entity) | ||
125 | #define link_top(en) ((en)->stack[(en)->top].link) | 125 | #define link_top(en) ((en)->stack[(en)->top].link) |
126 | #define stack_top(en) ((en)->stack[(en)->top].entity) | 126 | #define stack_top(en) ((en)->stack[(en)->top].entity) |
127 | 127 | ||
@@ -140,6 +140,12 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph, | |||
140 | { | 140 | { |
141 | graph->top = 0; | 141 | graph->top = 0; |
142 | graph->stack[graph->top].entity = NULL; | 142 | graph->stack[graph->top].entity = NULL; |
143 | bitmap_zero(graph->entities, MEDIA_ENTITY_ENUM_MAX_ID); | ||
144 | |||
145 | if (WARN_ON(entity->id >= MEDIA_ENTITY_ENUM_MAX_ID)) | ||
146 | return; | ||
147 | |||
148 | __set_bit(entity->id, graph->entities); | ||
143 | stack_push(graph, entity); | 149 | stack_push(graph, entity); |
144 | } | 150 | } |
145 | EXPORT_SYMBOL_GPL(media_entity_graph_walk_start); | 151 | EXPORT_SYMBOL_GPL(media_entity_graph_walk_start); |
@@ -180,9 +186,11 @@ media_entity_graph_walk_next(struct media_entity_graph *graph) | |||
180 | 186 | ||
181 | /* Get the entity in the other end of the link . */ | 187 | /* Get the entity in the other end of the link . */ |
182 | next = media_entity_other(entity, link); | 188 | next = media_entity_other(entity, link); |
189 | if (WARN_ON(next->id >= MEDIA_ENTITY_ENUM_MAX_ID)) | ||
190 | return NULL; | ||
183 | 191 | ||
184 | /* Was it the entity we came here from? */ | 192 | /* Has the entity already been visited? */ |
185 | if (next == stack_peek(graph)) { | 193 | if (__test_and_set_bit(next->id, graph->entities)) { |
186 | link_top(graph)++; | 194 | link_top(graph)++; |
187 | continue; | 195 | continue; |
188 | } | 196 | } |
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index e564aac0aa30..d85cb0ace4dc 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c | |||
@@ -4441,9 +4441,7 @@ static void tibetCS16_init(struct bttv *btv) | |||
4441 | * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical | 4441 | * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical |
4442 | * unit 3, the second (which is the master) is logical unit 0, etc. | 4442 | * unit 3, the second (which is the master) is logical unit 0, etc. |
4443 | * We need to maintain the status of the analog switch (which of the 16 | 4443 | * We need to maintain the status of the analog switch (which of the 16 |
4444 | * cameras is connected to which of the 4 controllers). Rather than | 4444 | * cameras is connected to which of the 4 controllers) in sw_status array. |
4445 | * add to the bttv structure for this, we use the data reserved for | ||
4446 | * the mbox (unused for this card type). | ||
4447 | */ | 4445 | */ |
4448 | 4446 | ||
4449 | /* | 4447 | /* |
@@ -4478,7 +4476,6 @@ static void kodicom4400r_write(struct bttv *btv, | |||
4478 | */ | 4476 | */ |
4479 | static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) | 4477 | static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) |
4480 | { | 4478 | { |
4481 | char *sw_status; | ||
4482 | int xaddr, yaddr; | 4479 | int xaddr, yaddr; |
4483 | struct bttv *mctlr; | 4480 | struct bttv *mctlr; |
4484 | static unsigned char map[4] = {3, 0, 2, 1}; | 4481 | static unsigned char map[4] = {3, 0, 2, 1}; |
@@ -4489,14 +4486,13 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) | |||
4489 | } | 4486 | } |
4490 | yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */ | 4487 | yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */ |
4491 | yaddr = map[yaddr]; | 4488 | yaddr = map[yaddr]; |
4492 | sw_status = (char *)(&mctlr->mbox_we); | ||
4493 | xaddr = input & 0xf; | 4489 | xaddr = input & 0xf; |
4494 | /* Check if the controller/camera pair has changed, else ignore */ | 4490 | /* Check if the controller/camera pair has changed, else ignore */ |
4495 | if (sw_status[yaddr] != xaddr) | 4491 | if (mctlr->sw_status[yaddr] != xaddr) |
4496 | { | 4492 | { |
4497 | /* "open" the old switch, "close" the new one, save the new */ | 4493 | /* "open" the old switch, "close" the new one, save the new */ |
4498 | kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0); | 4494 | kodicom4400r_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0); |
4499 | sw_status[yaddr] = xaddr; | 4495 | mctlr->sw_status[yaddr] = xaddr; |
4500 | kodicom4400r_write(mctlr, xaddr, yaddr, 1); | 4496 | kodicom4400r_write(mctlr, xaddr, yaddr, 1); |
4501 | } | 4497 | } |
4502 | } | 4498 | } |
@@ -4509,7 +4505,6 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) | |||
4509 | */ | 4505 | */ |
4510 | static void kodicom4400r_init(struct bttv *btv) | 4506 | static void kodicom4400r_init(struct bttv *btv) |
4511 | { | 4507 | { |
4512 | char *sw_status = (char *)(&btv->mbox_we); | ||
4513 | int ix; | 4508 | int ix; |
4514 | 4509 | ||
4515 | gpio_inout(0x0003ff, 0x0003ff); | 4510 | gpio_inout(0x0003ff, 0x0003ff); |
@@ -4517,7 +4512,7 @@ static void kodicom4400r_init(struct bttv *btv) | |||
4517 | gpio_write(0); | 4512 | gpio_write(0); |
4518 | /* Preset camera 0 to the 4 controllers */ | 4513 | /* Preset camera 0 to the 4 controllers */ |
4519 | for (ix = 0; ix < 4; ix++) { | 4514 | for (ix = 0; ix < 4; ix++) { |
4520 | sw_status[ix] = ix; | 4515 | btv->sw_status[ix] = ix; |
4521 | kodicom4400r_write(btv, ix, ix, 1); | 4516 | kodicom4400r_write(btv, ix, ix, 1); |
4522 | } | 4517 | } |
4523 | /* | 4518 | /* |
@@ -4794,7 +4789,6 @@ static void gv800s_write(struct bttv *btv, | |||
4794 | static void gv800s_muxsel(struct bttv *btv, unsigned int input) | 4789 | static void gv800s_muxsel(struct bttv *btv, unsigned int input) |
4795 | { | 4790 | { |
4796 | struct bttv *mctlr; | 4791 | struct bttv *mctlr; |
4797 | char *sw_status; | ||
4798 | int xaddr, yaddr; | 4792 | int xaddr, yaddr; |
4799 | static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 }, | 4793 | static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 }, |
4800 | { 0x1, 0x5, 0xb, 0x7 }, | 4794 | { 0x1, 0x5, 0xb, 0x7 }, |
@@ -4807,14 +4801,13 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input) | |||
4807 | return; | 4801 | return; |
4808 | } | 4802 | } |
4809 | yaddr = (btv->c.nr - mctlr->c.nr) & 3; | 4803 | yaddr = (btv->c.nr - mctlr->c.nr) & 3; |
4810 | sw_status = (char *)(&mctlr->mbox_we); | ||
4811 | xaddr = map[yaddr][input] & 0xf; | 4804 | xaddr = map[yaddr][input] & 0xf; |
4812 | 4805 | ||
4813 | /* Check if the controller/camera pair has changed, ignore otherwise */ | 4806 | /* Check if the controller/camera pair has changed, ignore otherwise */ |
4814 | if (sw_status[yaddr] != xaddr) { | 4807 | if (mctlr->sw_status[yaddr] != xaddr) { |
4815 | /* disable the old switch, enable the new one and save status */ | 4808 | /* disable the old switch, enable the new one and save status */ |
4816 | gv800s_write(mctlr, sw_status[yaddr], yaddr, 0); | 4809 | gv800s_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0); |
4817 | sw_status[yaddr] = xaddr; | 4810 | mctlr->sw_status[yaddr] = xaddr; |
4818 | gv800s_write(mctlr, xaddr, yaddr, 1); | 4811 | gv800s_write(mctlr, xaddr, yaddr, 1); |
4819 | } | 4812 | } |
4820 | } | 4813 | } |
@@ -4822,7 +4815,6 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input) | |||
4822 | /* GeoVision GV-800(S) "master" chip init */ | 4815 | /* GeoVision GV-800(S) "master" chip init */ |
4823 | static void gv800s_init(struct bttv *btv) | 4816 | static void gv800s_init(struct bttv *btv) |
4824 | { | 4817 | { |
4825 | char *sw_status = (char *)(&btv->mbox_we); | ||
4826 | int ix; | 4818 | int ix; |
4827 | 4819 | ||
4828 | gpio_inout(0xf107f, 0xf107f); | 4820 | gpio_inout(0xf107f, 0xf107f); |
@@ -4831,7 +4823,7 @@ static void gv800s_init(struct bttv *btv) | |||
4831 | 4823 | ||
4832 | /* Preset camera 0 to the 4 controllers */ | 4824 | /* Preset camera 0 to the 4 controllers */ |
4833 | for (ix = 0; ix < 4; ix++) { | 4825 | for (ix = 0; ix < 4; ix++) { |
4834 | sw_status[ix] = ix; | 4826 | btv->sw_status[ix] = ix; |
4835 | gv800s_write(btv, ix, ix, 1); | 4827 | gv800s_write(btv, ix, ix, 1); |
4836 | } | 4828 | } |
4837 | 4829 | ||
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index 9c1cc2c50ee2..6eefb595d0fa 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h | |||
@@ -459,6 +459,9 @@ struct bttv { | |||
459 | int mbox_iow; | 459 | int mbox_iow; |
460 | int mbox_csel; | 460 | int mbox_csel; |
461 | 461 | ||
462 | /* switch status for multi-controller cards */ | ||
463 | char sw_status[4]; | ||
464 | |||
462 | /* risc memory management data | 465 | /* risc memory management data |
463 | - must acquire s_lock before changing these | 466 | - must acquire s_lock before changing these |
464 | - only the irq handler is supported to touch top + bottom + vcurr */ | 467 | - only the irq handler is supported to touch top + bottom + vcurr */ |
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig index b3688aa8acc3..5104c802f72f 100644 --- a/drivers/media/pci/cx23885/Kconfig +++ b/drivers/media/pci/cx23885/Kconfig | |||
@@ -29,6 +29,7 @@ config VIDEO_CX23885 | |||
29 | select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT | 29 | select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT |
30 | select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT | 30 | select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT |
31 | select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT | 31 | select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT |
32 | select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT | ||
32 | select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT | 33 | select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT |
33 | select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT | 34 | select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT |
34 | select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT | 35 | select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT |
diff --git a/drivers/media/pci/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c index e958a01fd554..c443b7ac5adf 100644 --- a/drivers/media/pci/cx23885/cx23885-av.c +++ b/drivers/media/pci/cx23885/cx23885-av.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "cx23885.h" | 24 | #include "cx23885.h" |
25 | #include "cx23885-av.h" | 25 | #include "cx23885-av.h" |
26 | #include "cx23885-video.h" | ||
26 | 27 | ||
27 | void cx23885_av_work_handler(struct work_struct *work) | 28 | void cx23885_av_work_handler(struct work_struct *work) |
28 | { | 29 | { |
@@ -32,5 +33,17 @@ void cx23885_av_work_handler(struct work_struct *work) | |||
32 | 33 | ||
33 | v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine, | 34 | v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine, |
34 | PCI_MSK_AV_CORE, &handled); | 35 | PCI_MSK_AV_CORE, &handled); |
36 | |||
37 | /* Getting here with the interrupt not handled | ||
38 | then probbaly flatiron does have pending interrupts. | ||
39 | */ | ||
40 | if (!handled) { | ||
41 | /* clear left and right adc channel interrupt request flag */ | ||
42 | cx23885_flatiron_write(dev, 0x1f, | ||
43 | cx23885_flatiron_read(dev, 0x1f) | 0x80); | ||
44 | cx23885_flatiron_write(dev, 0x23, | ||
45 | cx23885_flatiron_read(dev, 0x23) | 0x80); | ||
46 | } | ||
47 | |||
35 | cx23885_irq_enable(dev, PCI_MSK_AV_CORE); | 48 | cx23885_irq_enable(dev, PCI_MSK_AV_CORE); |
36 | } | 49 | } |
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 7e923f8dd2f5..6a71a965e757 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c | |||
@@ -528,11 +528,12 @@ struct cx23885_board cx23885_boards[] = { | |||
528 | } }, | 528 | } }, |
529 | }, | 529 | }, |
530 | [CX23885_BOARD_MYGICA_X8507] = { | 530 | [CX23885_BOARD_MYGICA_X8507] = { |
531 | .name = "Mygica X8507", | 531 | .name = "Mygica X8502/X8507 ISDB-T", |
532 | .tuner_type = TUNER_XC5000, | 532 | .tuner_type = TUNER_XC5000, |
533 | .tuner_addr = 0x61, | 533 | .tuner_addr = 0x61, |
534 | .tuner_bus = 1, | 534 | .tuner_bus = 1, |
535 | .porta = CX23885_ANALOG_VIDEO, | 535 | .porta = CX23885_ANALOG_VIDEO, |
536 | .portb = CX23885_MPEG_DVB, | ||
536 | .input = { | 537 | .input = { |
537 | { | 538 | { |
538 | .type = CX23885_VMUX_TELEVISION, | 539 | .type = CX23885_VMUX_TELEVISION, |
@@ -1281,7 +1282,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
1281 | case CX23885_BOARD_MYGICA_X8507: | 1282 | case CX23885_BOARD_MYGICA_X8507: |
1282 | /* GPIO-0 (0)Analog / (1)Digital TV */ | 1283 | /* GPIO-0 (0)Analog / (1)Digital TV */ |
1283 | /* GPIO-1 reset XC5000 */ | 1284 | /* GPIO-1 reset XC5000 */ |
1284 | /* GPIO-2 reset LGS8GL5 / LGS8G75 */ | 1285 | /* GPIO-2 demod reset */ |
1285 | cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1); | 1286 | cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1); |
1286 | cx23885_gpio_clear(dev, GPIO_1 | GPIO_2); | 1287 | cx23885_gpio_clear(dev, GPIO_1 | GPIO_2); |
1287 | mdelay(100); | 1288 | mdelay(100); |
@@ -1677,6 +1678,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1677 | break; | 1678 | break; |
1678 | case CX23885_BOARD_MYGICA_X8506: | 1679 | case CX23885_BOARD_MYGICA_X8506: |
1679 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 1680 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
1681 | case CX23885_BOARD_MYGICA_X8507: | ||
1680 | ts1->gen_ctrl_val = 0x5; /* Parallel */ | 1682 | ts1->gen_ctrl_val = 0x5; /* Parallel */ |
1681 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 1683 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
1682 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 1684 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; |
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index 268654ac9a9f..9f63d93239ec 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c | |||
@@ -1941,10 +1941,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) | |||
1941 | 1941 | ||
1942 | if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) { | 1942 | if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) { |
1943 | cx23885_irq_disable(dev, PCI_MSK_AV_CORE); | 1943 | cx23885_irq_disable(dev, PCI_MSK_AV_CORE); |
1944 | if (!schedule_work(&dev->cx25840_work)) | 1944 | schedule_work(&dev->cx25840_work); |
1945 | printk(KERN_ERR "%s: failed to set up deferred work for" | ||
1946 | " AV Core/IR interrupt. Interrupt is disabled" | ||
1947 | " and won't be re-enabled\n", dev->name); | ||
1948 | handled++; | 1945 | handled++; |
1949 | } | 1946 | } |
1950 | 1947 | ||
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 9c5ed10b2c5e..971e4ff1b87f 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c | |||
@@ -69,6 +69,7 @@ | |||
69 | #include "stb6100_cfg.h" | 69 | #include "stb6100_cfg.h" |
70 | #include "tda10071.h" | 70 | #include "tda10071.h" |
71 | #include "a8293.h" | 71 | #include "a8293.h" |
72 | #include "mb86a20s.h" | ||
72 | 73 | ||
73 | static unsigned int debug; | 74 | static unsigned int debug; |
74 | 75 | ||
@@ -119,8 +120,6 @@ static void dvb_buf_release(struct videobuf_queue *q, | |||
119 | cx23885_free_buffer(q, (struct cx23885_buffer *)vb); | 120 | cx23885_free_buffer(q, (struct cx23885_buffer *)vb); |
120 | } | 121 | } |
121 | 122 | ||
122 | static int cx23885_dvb_set_frontend(struct dvb_frontend *fe); | ||
123 | |||
124 | static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) | 123 | static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) |
125 | { | 124 | { |
126 | struct videobuf_dvb_frontends *f; | 125 | struct videobuf_dvb_frontends *f; |
@@ -135,12 +134,6 @@ static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) | |||
135 | 134 | ||
136 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) | 135 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) |
137 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); | 136 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); |
138 | |||
139 | /* | ||
140 | * FIXME: Improve this path to avoid calling the | ||
141 | * cx23885_dvb_set_frontend() every time it passes here. | ||
142 | */ | ||
143 | cx23885_dvb_set_frontend(fe->dvb.frontend); | ||
144 | } | 137 | } |
145 | 138 | ||
146 | static struct videobuf_queue_ops dvb_qops = { | 139 | static struct videobuf_queue_ops dvb_qops = { |
@@ -500,6 +493,15 @@ static struct xc5000_config mygica_x8506_xc5000_config = { | |||
500 | .if_khz = 5380, | 493 | .if_khz = 5380, |
501 | }; | 494 | }; |
502 | 495 | ||
496 | static struct mb86a20s_config mygica_x8507_mb86a20s_config = { | ||
497 | .demod_address = 0x10, | ||
498 | }; | ||
499 | |||
500 | static struct xc5000_config mygica_x8507_xc5000_config = { | ||
501 | .i2c_address = 0x61, | ||
502 | .if_khz = 4000, | ||
503 | }; | ||
504 | |||
503 | static struct stv090x_config prof_8000_stv090x_config = { | 505 | static struct stv090x_config prof_8000_stv090x_config = { |
504 | .device = STV0903, | 506 | .device = STV0903, |
505 | .demod_mode = STV090x_SINGLE, | 507 | .demod_mode = STV090x_SINGLE, |
@@ -556,14 +558,27 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe) | |||
556 | } | 558 | } |
557 | break; | 559 | break; |
558 | case CX23885_BOARD_MYGICA_X8506: | 560 | case CX23885_BOARD_MYGICA_X8506: |
561 | case CX23885_BOARD_MYGICA_X8507: | ||
559 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 562 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
560 | /* Select Digital TV */ | 563 | /* Select Digital TV */ |
561 | cx23885_gpio_set(dev, GPIO_0); | 564 | cx23885_gpio_set(dev, GPIO_0); |
562 | break; | 565 | break; |
563 | } | 566 | } |
567 | |||
568 | /* Call the real set_frontend */ | ||
569 | if (port->set_frontend) | ||
570 | return port->set_frontend(fe); | ||
571 | |||
564 | return 0; | 572 | return 0; |
565 | } | 573 | } |
566 | 574 | ||
575 | static void cx23885_set_frontend_hook(struct cx23885_tsport *port, | ||
576 | struct dvb_frontend *fe) | ||
577 | { | ||
578 | port->set_frontend = fe->ops.set_frontend; | ||
579 | fe->ops.set_frontend = cx23885_dvb_set_frontend; | ||
580 | } | ||
581 | |||
567 | static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { | 582 | static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { |
568 | .prod = LGS8GXX_PROD_LGS8G75, | 583 | .prod = LGS8GXX_PROD_LGS8G75, |
569 | .demod_address = 0x19, | 584 | .demod_address = 0x19, |
@@ -771,6 +786,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
771 | 0x60, &dev->i2c_bus[1].i2c_adap, | 786 | 0x60, &dev->i2c_bus[1].i2c_adap, |
772 | &hauppauge_hvr127x_config); | 787 | &hauppauge_hvr127x_config); |
773 | } | 788 | } |
789 | if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1275) | ||
790 | cx23885_set_frontend_hook(port, fe0->dvb.frontend); | ||
774 | break; | 791 | break; |
775 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 792 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
776 | case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: | 793 | case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: |
@@ -1106,6 +1123,21 @@ static int dvb_register(struct cx23885_tsport *port) | |||
1106 | &i2c_bus2->i2c_adap, | 1123 | &i2c_bus2->i2c_adap, |
1107 | &mygica_x8506_xc5000_config); | 1124 | &mygica_x8506_xc5000_config); |
1108 | } | 1125 | } |
1126 | cx23885_set_frontend_hook(port, fe0->dvb.frontend); | ||
1127 | break; | ||
1128 | case CX23885_BOARD_MYGICA_X8507: | ||
1129 | i2c_bus = &dev->i2c_bus[0]; | ||
1130 | i2c_bus2 = &dev->i2c_bus[1]; | ||
1131 | fe0->dvb.frontend = dvb_attach(mb86a20s_attach, | ||
1132 | &mygica_x8507_mb86a20s_config, | ||
1133 | &i2c_bus->i2c_adap); | ||
1134 | if (fe0->dvb.frontend != NULL) { | ||
1135 | dvb_attach(xc5000_attach, | ||
1136 | fe0->dvb.frontend, | ||
1137 | &i2c_bus2->i2c_adap, | ||
1138 | &mygica_x8507_xc5000_config); | ||
1139 | } | ||
1140 | cx23885_set_frontend_hook(port, fe0->dvb.frontend); | ||
1109 | break; | 1141 | break; |
1110 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 1142 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
1111 | i2c_bus = &dev->i2c_bus[0]; | 1143 | i2c_bus = &dev->i2c_bus[0]; |
@@ -1119,6 +1151,7 @@ static int dvb_register(struct cx23885_tsport *port) | |||
1119 | &i2c_bus2->i2c_adap, | 1151 | &i2c_bus2->i2c_adap, |
1120 | &magicpro_prohdtve2_xc5000_config); | 1152 | &magicpro_prohdtve2_xc5000_config); |
1121 | } | 1153 | } |
1154 | cx23885_set_frontend_hook(port, fe0->dvb.frontend); | ||
1122 | break; | 1155 | break; |
1123 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 1156 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
1124 | i2c_bus = &dev->i2c_bus[0]; | 1157 | i2c_bus = &dev->i2c_bus[0]; |
@@ -1249,6 +1282,10 @@ static int dvb_register(struct cx23885_tsport *port) | |||
1249 | fe0->dvb.frontend = dvb_attach(ds3000_attach, | 1282 | fe0->dvb.frontend = dvb_attach(ds3000_attach, |
1250 | &tevii_ds3000_config, | 1283 | &tevii_ds3000_config, |
1251 | &i2c_bus->i2c_adap); | 1284 | &i2c_bus->i2c_adap); |
1285 | if (fe0->dvb.frontend != NULL) { | ||
1286 | dvb_attach(ts2020_attach, fe0->dvb.frontend, | ||
1287 | &tevii_ts2020_config, &i2c_bus->i2c_adap); | ||
1288 | } | ||
1252 | break; | 1289 | break; |
1253 | case CX23885_BOARD_PROF_8000: | 1290 | case CX23885_BOARD_PROF_8000: |
1254 | i2c_bus = &dev->i2c_bus[0]; | 1291 | i2c_bus = &dev->i2c_bus[0]; |
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index e33d1a7dfdd0..161686832b20 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/div64.h> | 32 | #include <asm/div64.h> |
33 | 33 | ||
34 | #include "cx23885.h" | 34 | #include "cx23885.h" |
35 | #include "cx23885-video.h" | ||
35 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
36 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
37 | #include "cx23885-ioctl.h" | 38 | #include "cx23885-ioctl.h" |
@@ -417,7 +418,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, | |||
417 | mutex_unlock(&dev->lock); | 418 | mutex_unlock(&dev->lock); |
418 | } | 419 | } |
419 | 420 | ||
420 | static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data) | 421 | int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data) |
421 | { | 422 | { |
422 | /* 8 bit registers, 8 bit values */ | 423 | /* 8 bit registers, 8 bit values */ |
423 | u8 buf[] = { reg, data }; | 424 | u8 buf[] = { reg, data }; |
@@ -428,7 +429,7 @@ static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data) | |||
428 | return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1); | 429 | return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1); |
429 | } | 430 | } |
430 | 431 | ||
431 | static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg) | 432 | u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg) |
432 | { | 433 | { |
433 | /* 8 bit registers, 8 bit values */ | 434 | /* 8 bit registers, 8 bit values */ |
434 | int ret; | 435 | int ret; |
diff --git a/drivers/media/pci/cx23885/cx23885-video.h b/drivers/media/pci/cx23885/cx23885-video.h new file mode 100644 index 000000000000..c961a2b0de0f --- /dev/null +++ b/drivers/media/pci/cx23885/cx23885-video.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
19 | * 02110-1301, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef _CX23885_VIDEO_H_ | ||
23 | #define _CX23885_VIDEO_H_ | ||
24 | int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data); | ||
25 | u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg); | ||
26 | #endif | ||
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index 5687d3f678db..038caf53908b 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h | |||
@@ -320,6 +320,8 @@ struct cx23885_tsport { | |||
320 | 320 | ||
321 | /* Workaround for a temp dvb_frontend that the tuner can attached to */ | 321 | /* Workaround for a temp dvb_frontend that the tuner can attached to */ |
322 | struct dvb_frontend analog_fe; | 322 | struct dvb_frontend analog_fe; |
323 | |||
324 | int (*set_frontend)(struct dvb_frontend *fe); | ||
323 | }; | 325 | }; |
324 | 326 | ||
325 | struct cx23885_kernel_ir { | 327 | struct cx23885_kernel_ir { |
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig index bb05eca2da29..a63a9ad163b2 100644 --- a/drivers/media/pci/cx88/Kconfig +++ b/drivers/media/pci/cx88/Kconfig | |||
@@ -72,9 +72,9 @@ config VIDEO_CX88_DVB | |||
72 | To compile this driver as a module, choose M here: the | 72 | To compile this driver as a module, choose M here: the |
73 | module will be called cx88-dvb. | 73 | module will be called cx88-dvb. |
74 | 74 | ||
75 | config VIDEO_CX88_VP3054 | 75 | config VIDEO_CX88_ENABLE_VP3054 |
76 | tristate "VP-3054 Secondary I2C Bus Support" | 76 | bool "VP-3054 Secondary I2C Bus Support" |
77 | default m | 77 | default y |
78 | depends on VIDEO_CX88_DVB && DVB_MT352 | 78 | depends on VIDEO_CX88_DVB && DVB_MT352 |
79 | ---help--- | 79 | ---help--- |
80 | This adds DVB-T support for cards based on the | 80 | This adds DVB-T support for cards based on the |
@@ -82,6 +82,11 @@ config VIDEO_CX88_VP3054 | |||
82 | which also require support for the VP-3054 | 82 | which also require support for the VP-3054 |
83 | Secondary I2C bus, such at DNTV Live! DVB-T Pro. | 83 | Secondary I2C bus, such at DNTV Live! DVB-T Pro. |
84 | 84 | ||
85 | config VIDEO_CX88_VP3054 | ||
86 | tristate | ||
87 | depends on VIDEO_CX88_DVB && VIDEO_CX88_ENABLE_VP3054 | ||
88 | default y | ||
89 | |||
85 | config VIDEO_CX88_MPEG | 90 | config VIDEO_CX88_MPEG |
86 | tristate | 91 | tristate |
87 | depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD | 92 | depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD |
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index afe0eaea81b4..28893a6b249e 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h | |||
@@ -259,7 +259,7 @@ struct cx88_input { | |||
259 | }; | 259 | }; |
260 | 260 | ||
261 | enum cx88_audio_chip { | 261 | enum cx88_audio_chip { |
262 | CX88_AUDIO_WM8775, | 262 | CX88_AUDIO_WM8775 = 1, |
263 | CX88_AUDIO_TVAUDIO, | 263 | CX88_AUDIO_TVAUDIO, |
264 | }; | 264 | }; |
265 | 265 | ||
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 08de865cc399..8068d7b64155 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig | |||
@@ -203,13 +203,23 @@ config VIDEO_SAMSUNG_EXYNOS_GSC | |||
203 | 203 | ||
204 | config VIDEO_SH_VEU | 204 | config VIDEO_SH_VEU |
205 | tristate "SuperH VEU mem2mem video processing driver" | 205 | tristate "SuperH VEU mem2mem video processing driver" |
206 | depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS | 206 | depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS && HAS_DMA |
207 | select VIDEOBUF2_DMA_CONTIG | 207 | select VIDEOBUF2_DMA_CONTIG |
208 | select V4L2_MEM2MEM_DEV | 208 | select V4L2_MEM2MEM_DEV |
209 | help | 209 | help |
210 | Support for the Video Engine Unit (VEU) on SuperH and | 210 | Support for the Video Engine Unit (VEU) on SuperH and |
211 | SH-Mobile SoCs. | 211 | SH-Mobile SoCs. |
212 | 212 | ||
213 | config VIDEO_RENESAS_VSP1 | ||
214 | tristate "Renesas VSP1 Video Processing Engine" | ||
215 | depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API | ||
216 | select VIDEOBUF2_DMA_CONTIG | ||
217 | ---help--- | ||
218 | This is a V4L2 driver for the Renesas VSP1 video processing engine. | ||
219 | |||
220 | To compile this driver as a module, choose M here: the module | ||
221 | will be called vsp1. | ||
222 | |||
213 | endif # V4L_MEM2MEM_DRIVERS | 223 | endif # V4L_MEM2MEM_DRIVERS |
214 | 224 | ||
215 | menuconfig V4L_TEST_DRIVERS | 225 | menuconfig V4L_TEST_DRIVERS |
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index eee28dd78d7d..4e4da482c522 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile | |||
@@ -46,6 +46,8 @@ obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o | |||
46 | 46 | ||
47 | obj-$(CONFIG_SOC_CAMERA) += soc_camera/ | 47 | obj-$(CONFIG_SOC_CAMERA) += soc_camera/ |
48 | 48 | ||
49 | obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ | ||
50 | |||
49 | obj-y += davinci/ | 51 | obj-y += davinci/ |
50 | 52 | ||
51 | obj-$(CONFIG_ARCH_OMAP) += omap/ | 53 | obj-$(CONFIG_ARCH_OMAP) += omap/ |
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 7f838c681cea..4c1105977090 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c | |||
@@ -388,13 +388,8 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
388 | 388 | ||
389 | params.hdelay = bt->hsync + bt->hbackporch; | 389 | params.hdelay = bt->hsync + bt->hbackporch; |
390 | params.vdelay = bt->vsync + bt->vbackporch; | 390 | params.vdelay = bt->vsync + bt->vbackporch; |
391 | params.line = bt->hfrontporch + bt->hsync | 391 | params.line = V4L2_DV_BT_FRAME_WIDTH(bt); |
392 | + bt->hbackporch + bt->width; | 392 | params.frame = V4L2_DV_BT_FRAME_HEIGHT(bt); |
393 | params.frame = bt->vfrontporch + bt->vsync | ||
394 | + bt->vbackporch + bt->height; | ||
395 | if (bt->interlaced) | ||
396 | params.frame += bt->il_vfrontporch + bt->il_vsync | ||
397 | + bt->il_vbackporch; | ||
398 | } else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities | 393 | } else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities |
399 | & V4L2_IN_CAP_STD) { | 394 | & V4L2_IN_CAP_STD) { |
400 | params.hdelay = 0; | 395 | params.hdelay = 0; |
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index bd9405df1bd6..449d2fec9e87 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | #include <linux/kfifo.h> | ||
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
@@ -28,6 +29,7 @@ | |||
28 | 29 | ||
29 | #include <media/v4l2-ctrls.h> | 30 | #include <media/v4l2-ctrls.h> |
30 | #include <media/v4l2-device.h> | 31 | #include <media/v4l2-device.h> |
32 | #include <media/v4l2-event.h> | ||
31 | #include <media/v4l2-ioctl.h> | 33 | #include <media/v4l2-ioctl.h> |
32 | #include <media/v4l2-mem2mem.h> | 34 | #include <media/v4l2-mem2mem.h> |
33 | #include <media/videobuf2-core.h> | 35 | #include <media/videobuf2-core.h> |
@@ -41,13 +43,16 @@ | |||
41 | 43 | ||
42 | #define CODA_FMO_BUF_SIZE 32 | 44 | #define CODA_FMO_BUF_SIZE 32 |
43 | #define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) | 45 | #define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) |
44 | #define CODA7_WORK_BUF_SIZE (512 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) | 46 | #define CODA7_WORK_BUF_SIZE (128 * 1024) |
47 | #define CODA7_TEMP_BUF_SIZE (304 * 1024) | ||
45 | #define CODA_PARA_BUF_SIZE (10 * 1024) | 48 | #define CODA_PARA_BUF_SIZE (10 * 1024) |
46 | #define CODA_ISRAM_SIZE (2048 * 2) | 49 | #define CODA_ISRAM_SIZE (2048 * 2) |
47 | #define CODADX6_IRAM_SIZE 0xb000 | 50 | #define CODADX6_IRAM_SIZE 0xb000 |
48 | #define CODA7_IRAM_SIZE 0x14000 /* 81920 bytes */ | 51 | #define CODA7_IRAM_SIZE 0x14000 |
49 | 52 | ||
50 | #define CODA_MAX_FRAMEBUFFERS 2 | 53 | #define CODA7_PS_BUF_SIZE 0x28000 |
54 | |||
55 | #define CODA_MAX_FRAMEBUFFERS 8 | ||
51 | 56 | ||
52 | #define MAX_W 8192 | 57 | #define MAX_W 8192 |
53 | #define MAX_H 8192 | 58 | #define MAX_H 8192 |
@@ -129,6 +134,7 @@ struct coda_dev { | |||
129 | struct clk *clk_ahb; | 134 | struct clk *clk_ahb; |
130 | 135 | ||
131 | struct coda_aux_buf codebuf; | 136 | struct coda_aux_buf codebuf; |
137 | struct coda_aux_buf tempbuf; | ||
132 | struct coda_aux_buf workbuf; | 138 | struct coda_aux_buf workbuf; |
133 | struct gen_pool *iram_pool; | 139 | struct gen_pool *iram_pool; |
134 | long unsigned int iram_vaddr; | 140 | long unsigned int iram_vaddr; |
@@ -153,6 +159,7 @@ struct coda_params { | |||
153 | u8 mpeg4_inter_qp; | 159 | u8 mpeg4_inter_qp; |
154 | u8 gop_size; | 160 | u8 gop_size; |
155 | int codec_mode; | 161 | int codec_mode; |
162 | int codec_mode_aux; | ||
156 | enum v4l2_mpeg_video_multi_slice_mode slice_mode; | 163 | enum v4l2_mpeg_video_multi_slice_mode slice_mode; |
157 | u32 framerate; | 164 | u32 framerate; |
158 | u16 bitrate; | 165 | u16 bitrate; |
@@ -160,13 +167,30 @@ struct coda_params { | |||
160 | u32 slice_max_mb; | 167 | u32 slice_max_mb; |
161 | }; | 168 | }; |
162 | 169 | ||
170 | struct coda_iram_info { | ||
171 | u32 axi_sram_use; | ||
172 | phys_addr_t buf_bit_use; | ||
173 | phys_addr_t buf_ip_ac_dc_use; | ||
174 | phys_addr_t buf_dbk_y_use; | ||
175 | phys_addr_t buf_dbk_c_use; | ||
176 | phys_addr_t buf_ovl_use; | ||
177 | phys_addr_t buf_btp_use; | ||
178 | phys_addr_t search_ram_paddr; | ||
179 | int search_ram_size; | ||
180 | }; | ||
181 | |||
163 | struct coda_ctx { | 182 | struct coda_ctx { |
164 | struct coda_dev *dev; | 183 | struct coda_dev *dev; |
184 | struct mutex buffer_mutex; | ||
165 | struct list_head list; | 185 | struct list_head list; |
186 | struct work_struct skip_run; | ||
166 | int aborting; | 187 | int aborting; |
188 | int initialized; | ||
167 | int streamon_out; | 189 | int streamon_out; |
168 | int streamon_cap; | 190 | int streamon_cap; |
169 | u32 isequence; | 191 | u32 isequence; |
192 | u32 qsequence; | ||
193 | u32 osequence; | ||
170 | struct coda_q_data q_data[2]; | 194 | struct coda_q_data q_data[2]; |
171 | enum coda_inst_type inst_type; | 195 | enum coda_inst_type inst_type; |
172 | struct coda_codec *codec; | 196 | struct coda_codec *codec; |
@@ -176,12 +200,25 @@ struct coda_ctx { | |||
176 | struct v4l2_ctrl_handler ctrls; | 200 | struct v4l2_ctrl_handler ctrls; |
177 | struct v4l2_fh fh; | 201 | struct v4l2_fh fh; |
178 | int gopcounter; | 202 | int gopcounter; |
203 | int runcounter; | ||
179 | char vpu_header[3][64]; | 204 | char vpu_header[3][64]; |
180 | int vpu_header_size[3]; | 205 | int vpu_header_size[3]; |
206 | struct kfifo bitstream_fifo; | ||
207 | struct mutex bitstream_mutex; | ||
208 | struct coda_aux_buf bitstream; | ||
209 | bool prescan_failed; | ||
181 | struct coda_aux_buf parabuf; | 210 | struct coda_aux_buf parabuf; |
211 | struct coda_aux_buf psbuf; | ||
212 | struct coda_aux_buf slicebuf; | ||
182 | struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; | 213 | struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; |
214 | struct coda_aux_buf workbuf; | ||
183 | int num_internal_frames; | 215 | int num_internal_frames; |
184 | int idx; | 216 | int idx; |
217 | int reg_idx; | ||
218 | struct coda_iram_info iram_info; | ||
219 | u32 bit_stream_param; | ||
220 | u32 frm_dis_flg; | ||
221 | int display_idx; | ||
185 | }; | 222 | }; |
186 | 223 | ||
187 | static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff, | 224 | static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff, |
@@ -228,10 +265,22 @@ static int coda_wait_timeout(struct coda_dev *dev) | |||
228 | static void coda_command_async(struct coda_ctx *ctx, int cmd) | 265 | static void coda_command_async(struct coda_ctx *ctx, int cmd) |
229 | { | 266 | { |
230 | struct coda_dev *dev = ctx->dev; | 267 | struct coda_dev *dev = ctx->dev; |
268 | |||
269 | if (dev->devtype->product == CODA_7541) { | ||
270 | /* Restore context related registers to CODA */ | ||
271 | coda_write(dev, ctx->bit_stream_param, | ||
272 | CODA_REG_BIT_BIT_STREAM_PARAM); | ||
273 | coda_write(dev, ctx->frm_dis_flg, | ||
274 | CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | ||
275 | coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); | ||
276 | } | ||
277 | |||
231 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); | 278 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); |
232 | 279 | ||
233 | coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); | 280 | coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); |
234 | coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD); | 281 | coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD); |
282 | coda_write(dev, ctx->params.codec_mode_aux, CODA7_REG_BIT_RUN_AUX_STD); | ||
283 | |||
235 | coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); | 284 | coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); |
236 | } | 285 | } |
237 | 286 | ||
@@ -297,6 +346,8 @@ static struct coda_codec codadx6_codecs[] = { | |||
297 | static struct coda_codec coda7_codecs[] = { | 346 | static struct coda_codec coda7_codecs[] = { |
298 | CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720), | 347 | CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720), |
299 | CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), | 348 | CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), |
349 | CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1080), | ||
350 | CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080), | ||
300 | }; | 351 | }; |
301 | 352 | ||
302 | static bool coda_format_is_yuv(u32 fourcc) | 353 | static bool coda_format_is_yuv(u32 fourcc) |
@@ -365,7 +416,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
365 | } | 416 | } |
366 | 417 | ||
367 | static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, | 418 | static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, |
368 | enum v4l2_buf_type type) | 419 | enum v4l2_buf_type type, int src_fourcc) |
369 | { | 420 | { |
370 | struct coda_ctx *ctx = fh_to_ctx(priv); | 421 | struct coda_ctx *ctx = fh_to_ctx(priv); |
371 | struct coda_codec *codecs = ctx->dev->devtype->codecs; | 422 | struct coda_codec *codecs = ctx->dev->devtype->codecs; |
@@ -377,7 +428,8 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, | |||
377 | 428 | ||
378 | for (i = 0; i < num_formats; i++) { | 429 | for (i = 0; i < num_formats; i++) { |
379 | /* Both uncompressed formats are always supported */ | 430 | /* Both uncompressed formats are always supported */ |
380 | if (coda_format_is_yuv(formats[i].fourcc)) { | 431 | if (coda_format_is_yuv(formats[i].fourcc) && |
432 | !coda_format_is_yuv(src_fourcc)) { | ||
381 | if (num == f->index) | 433 | if (num == f->index) |
382 | break; | 434 | break; |
383 | ++num; | 435 | ++num; |
@@ -385,8 +437,10 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, | |||
385 | } | 437 | } |
386 | /* Compressed formats may be supported, check the codec list */ | 438 | /* Compressed formats may be supported, check the codec list */ |
387 | for (k = 0; k < num_codecs; k++) { | 439 | for (k = 0; k < num_codecs; k++) { |
440 | /* if src_fourcc is set, only consider matching codecs */ | ||
388 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE && | 441 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE && |
389 | formats[i].fourcc == codecs[k].dst_fourcc) | 442 | formats[i].fourcc == codecs[k].dst_fourcc && |
443 | (!src_fourcc || src_fourcc == codecs[k].src_fourcc)) | ||
390 | break; | 444 | break; |
391 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | 445 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT && |
392 | formats[i].fourcc == codecs[k].src_fourcc) | 446 | formats[i].fourcc == codecs[k].src_fourcc) |
@@ -413,13 +467,26 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, | |||
413 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 467 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
414 | struct v4l2_fmtdesc *f) | 468 | struct v4l2_fmtdesc *f) |
415 | { | 469 | { |
416 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 470 | struct coda_ctx *ctx = fh_to_ctx(priv); |
471 | struct vb2_queue *src_vq; | ||
472 | struct coda_q_data *q_data_src; | ||
473 | |||
474 | /* If the source format is already fixed, only list matching formats */ | ||
475 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
476 | if (vb2_is_streaming(src_vq)) { | ||
477 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
478 | |||
479 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
480 | q_data_src->fourcc); | ||
481 | } | ||
482 | |||
483 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0); | ||
417 | } | 484 | } |
418 | 485 | ||
419 | static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, | 486 | static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, |
420 | struct v4l2_fmtdesc *f) | 487 | struct v4l2_fmtdesc *f) |
421 | { | 488 | { |
422 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 489 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT, 0); |
423 | } | 490 | } |
424 | 491 | ||
425 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | 492 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) |
@@ -492,15 +559,45 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
492 | struct v4l2_format *f) | 559 | struct v4l2_format *f) |
493 | { | 560 | { |
494 | struct coda_ctx *ctx = fh_to_ctx(priv); | 561 | struct coda_ctx *ctx = fh_to_ctx(priv); |
495 | struct coda_codec *codec = NULL; | 562 | struct coda_codec *codec; |
563 | struct vb2_queue *src_vq; | ||
564 | int ret; | ||
496 | 565 | ||
497 | /* Determine codec by the encoded format */ | 566 | /* |
498 | codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, | 567 | * If the source format is already fixed, try to find a codec that |
499 | f->fmt.pix.pixelformat); | 568 | * converts to the given destination format |
569 | */ | ||
570 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
571 | if (vb2_is_streaming(src_vq)) { | ||
572 | struct coda_q_data *q_data_src; | ||
573 | |||
574 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
575 | codec = coda_find_codec(ctx->dev, q_data_src->fourcc, | ||
576 | f->fmt.pix.pixelformat); | ||
577 | if (!codec) | ||
578 | return -EINVAL; | ||
579 | } else { | ||
580 | /* Otherwise determine codec by encoded format, if possible */ | ||
581 | codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, | ||
582 | f->fmt.pix.pixelformat); | ||
583 | } | ||
500 | 584 | ||
501 | f->fmt.pix.colorspace = ctx->colorspace; | 585 | f->fmt.pix.colorspace = ctx->colorspace; |
502 | 586 | ||
503 | return vidioc_try_fmt(codec, f); | 587 | ret = vidioc_try_fmt(codec, f); |
588 | if (ret < 0) | ||
589 | return ret; | ||
590 | |||
591 | /* The h.264 decoder only returns complete 16x16 macroblocks */ | ||
592 | if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) { | ||
593 | f->fmt.pix.width = round_up(f->fmt.pix.width, 16); | ||
594 | f->fmt.pix.height = round_up(f->fmt.pix.height, 16); | ||
595 | f->fmt.pix.bytesperline = f->fmt.pix.width; | ||
596 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * | ||
597 | f->fmt.pix.height * 3 / 2; | ||
598 | } | ||
599 | |||
600 | return 0; | ||
504 | } | 601 | } |
505 | 602 | ||
506 | static int vidioc_try_fmt_vid_out(struct file *file, void *priv, | 603 | static int vidioc_try_fmt_vid_out(struct file *file, void *priv, |
@@ -610,11 +707,35 @@ static int vidioc_expbuf(struct file *file, void *priv, | |||
610 | return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); | 707 | return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); |
611 | } | 708 | } |
612 | 709 | ||
710 | static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, | ||
711 | struct v4l2_buffer *buf) | ||
712 | { | ||
713 | struct vb2_queue *src_vq; | ||
714 | |||
715 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
716 | |||
717 | return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) && | ||
718 | (buf->sequence == (ctx->qsequence - 1))); | ||
719 | } | ||
720 | |||
613 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | 721 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) |
614 | { | 722 | { |
615 | struct coda_ctx *ctx = fh_to_ctx(priv); | 723 | struct coda_ctx *ctx = fh_to_ctx(priv); |
724 | int ret; | ||
725 | |||
726 | ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | ||
727 | |||
728 | /* If this is the last capture buffer, emit an end-of-stream event */ | ||
729 | if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && | ||
730 | coda_buf_is_end_of_stream(ctx, buf)) { | ||
731 | const struct v4l2_event eos_event = { | ||
732 | .type = V4L2_EVENT_EOS | ||
733 | }; | ||
616 | 734 | ||
617 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | 735 | v4l2_event_queue_fh(&ctx->fh, &eos_event); |
736 | } | ||
737 | |||
738 | return ret; | ||
618 | } | 739 | } |
619 | 740 | ||
620 | static int vidioc_create_bufs(struct file *file, void *priv, | 741 | static int vidioc_create_bufs(struct file *file, void *priv, |
@@ -637,8 +758,53 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
637 | enum v4l2_buf_type type) | 758 | enum v4l2_buf_type type) |
638 | { | 759 | { |
639 | struct coda_ctx *ctx = fh_to_ctx(priv); | 760 | struct coda_ctx *ctx = fh_to_ctx(priv); |
761 | int ret; | ||
640 | 762 | ||
641 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | 763 | /* |
764 | * This indirectly calls __vb2_queue_cancel, which dequeues all buffers. | ||
765 | * We therefore have to lock it against running hardware in this context, | ||
766 | * which still needs the buffers. | ||
767 | */ | ||
768 | mutex_lock(&ctx->buffer_mutex); | ||
769 | ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | ||
770 | mutex_unlock(&ctx->buffer_mutex); | ||
771 | |||
772 | return ret; | ||
773 | } | ||
774 | |||
775 | static int vidioc_decoder_cmd(struct file *file, void *fh, | ||
776 | struct v4l2_decoder_cmd *dc) | ||
777 | { | ||
778 | struct coda_ctx *ctx = fh_to_ctx(fh); | ||
779 | |||
780 | if (dc->cmd != V4L2_DEC_CMD_STOP) | ||
781 | return -EINVAL; | ||
782 | |||
783 | if ((dc->flags & V4L2_DEC_CMD_STOP_TO_BLACK) || | ||
784 | (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)) | ||
785 | return -EINVAL; | ||
786 | |||
787 | if (dc->stop.pts != 0) | ||
788 | return -EINVAL; | ||
789 | |||
790 | if (ctx->inst_type != CODA_INST_DECODER) | ||
791 | return -EINVAL; | ||
792 | |||
793 | /* Set the strem-end flag on this context */ | ||
794 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | ||
795 | |||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | static int vidioc_subscribe_event(struct v4l2_fh *fh, | ||
800 | const struct v4l2_event_subscription *sub) | ||
801 | { | ||
802 | switch (sub->type) { | ||
803 | case V4L2_EVENT_EOS: | ||
804 | return v4l2_event_subscribe(fh, sub, 0, NULL); | ||
805 | default: | ||
806 | return v4l2_ctrl_subscribe_event(fh, sub); | ||
807 | } | ||
642 | } | 808 | } |
643 | 809 | ||
644 | static const struct v4l2_ioctl_ops coda_ioctl_ops = { | 810 | static const struct v4l2_ioctl_ops coda_ioctl_ops = { |
@@ -664,14 +830,206 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { | |||
664 | 830 | ||
665 | .vidioc_streamon = vidioc_streamon, | 831 | .vidioc_streamon = vidioc_streamon, |
666 | .vidioc_streamoff = vidioc_streamoff, | 832 | .vidioc_streamoff = vidioc_streamoff, |
833 | |||
834 | .vidioc_decoder_cmd = vidioc_decoder_cmd, | ||
835 | |||
836 | .vidioc_subscribe_event = vidioc_subscribe_event, | ||
837 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
667 | }; | 838 | }; |
668 | 839 | ||
840 | static int coda_start_decoding(struct coda_ctx *ctx); | ||
841 | |||
842 | static void coda_skip_run(struct work_struct *work) | ||
843 | { | ||
844 | struct coda_ctx *ctx = container_of(work, struct coda_ctx, skip_run); | ||
845 | |||
846 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); | ||
847 | } | ||
848 | |||
849 | static inline int coda_get_bitstream_payload(struct coda_ctx *ctx) | ||
850 | { | ||
851 | return kfifo_len(&ctx->bitstream_fifo); | ||
852 | } | ||
853 | |||
854 | static void coda_kfifo_sync_from_device(struct coda_ctx *ctx) | ||
855 | { | ||
856 | struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; | ||
857 | struct coda_dev *dev = ctx->dev; | ||
858 | u32 rd_ptr; | ||
859 | |||
860 | rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); | ||
861 | kfifo->out = (kfifo->in & ~kfifo->mask) | | ||
862 | (rd_ptr - ctx->bitstream.paddr); | ||
863 | if (kfifo->out > kfifo->in) | ||
864 | kfifo->out -= kfifo->mask + 1; | ||
865 | } | ||
866 | |||
867 | static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx) | ||
868 | { | ||
869 | struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; | ||
870 | struct coda_dev *dev = ctx->dev; | ||
871 | u32 rd_ptr, wr_ptr; | ||
872 | |||
873 | rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask); | ||
874 | coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); | ||
875 | wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); | ||
876 | coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); | ||
877 | } | ||
878 | |||
879 | static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx) | ||
880 | { | ||
881 | struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; | ||
882 | struct coda_dev *dev = ctx->dev; | ||
883 | u32 wr_ptr; | ||
884 | |||
885 | wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); | ||
886 | coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); | ||
887 | } | ||
888 | |||
889 | static int coda_bitstream_queue(struct coda_ctx *ctx, struct vb2_buffer *src_buf) | ||
890 | { | ||
891 | u32 src_size = vb2_get_plane_payload(src_buf, 0); | ||
892 | u32 n; | ||
893 | |||
894 | n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0), src_size); | ||
895 | if (n < src_size) | ||
896 | return -ENOSPC; | ||
897 | |||
898 | dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx->bitstream.paddr, | ||
899 | ctx->bitstream.size, DMA_TO_DEVICE); | ||
900 | |||
901 | ctx->qsequence++; | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | static bool coda_bitstream_try_queue(struct coda_ctx *ctx, | ||
907 | struct vb2_buffer *src_buf) | ||
908 | { | ||
909 | int ret; | ||
910 | |||
911 | if (coda_get_bitstream_payload(ctx) + | ||
912 | vb2_get_plane_payload(src_buf, 0) + 512 >= ctx->bitstream.size) | ||
913 | return false; | ||
914 | |||
915 | if (vb2_plane_vaddr(src_buf, 0) == NULL) { | ||
916 | v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n"); | ||
917 | return true; | ||
918 | } | ||
919 | |||
920 | ret = coda_bitstream_queue(ctx, src_buf); | ||
921 | if (ret < 0) { | ||
922 | v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n"); | ||
923 | return false; | ||
924 | } | ||
925 | /* Sync read pointer to device */ | ||
926 | if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev)) | ||
927 | coda_kfifo_sync_to_device_write(ctx); | ||
928 | |||
929 | ctx->prescan_failed = false; | ||
930 | |||
931 | return true; | ||
932 | } | ||
933 | |||
934 | static void coda_fill_bitstream(struct coda_ctx *ctx) | ||
935 | { | ||
936 | struct vb2_buffer *src_buf; | ||
937 | |||
938 | while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) { | ||
939 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | ||
940 | |||
941 | if (coda_bitstream_try_queue(ctx, src_buf)) { | ||
942 | src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); | ||
943 | v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); | ||
944 | } else { | ||
945 | break; | ||
946 | } | ||
947 | } | ||
948 | } | ||
949 | |||
669 | /* | 950 | /* |
670 | * Mem-to-mem operations. | 951 | * Mem-to-mem operations. |
671 | */ | 952 | */ |
672 | static void coda_device_run(void *m2m_priv) | 953 | static int coda_prepare_decode(struct coda_ctx *ctx) |
954 | { | ||
955 | struct vb2_buffer *dst_buf; | ||
956 | struct coda_dev *dev = ctx->dev; | ||
957 | struct coda_q_data *q_data_dst; | ||
958 | u32 stridey, height; | ||
959 | u32 picture_y, picture_cb, picture_cr; | ||
960 | |||
961 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | ||
962 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
963 | |||
964 | if (ctx->params.rot_mode & CODA_ROT_90) { | ||
965 | stridey = q_data_dst->height; | ||
966 | height = q_data_dst->width; | ||
967 | } else { | ||
968 | stridey = q_data_dst->width; | ||
969 | height = q_data_dst->height; | ||
970 | } | ||
971 | |||
972 | /* Try to copy source buffer contents into the bitstream ringbuffer */ | ||
973 | mutex_lock(&ctx->bitstream_mutex); | ||
974 | coda_fill_bitstream(ctx); | ||
975 | mutex_unlock(&ctx->bitstream_mutex); | ||
976 | |||
977 | if (coda_get_bitstream_payload(ctx) < 512 && | ||
978 | (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { | ||
979 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
980 | "bitstream payload: %d, skipping\n", | ||
981 | coda_get_bitstream_payload(ctx)); | ||
982 | schedule_work(&ctx->skip_run); | ||
983 | return -EAGAIN; | ||
984 | } | ||
985 | |||
986 | /* Run coda_start_decoding (again) if not yet initialized */ | ||
987 | if (!ctx->initialized) { | ||
988 | int ret = coda_start_decoding(ctx); | ||
989 | if (ret < 0) { | ||
990 | v4l2_err(&dev->v4l2_dev, "failed to start decoding\n"); | ||
991 | schedule_work(&ctx->skip_run); | ||
992 | return -EAGAIN; | ||
993 | } else { | ||
994 | ctx->initialized = 1; | ||
995 | } | ||
996 | } | ||
997 | |||
998 | /* Set rotator output */ | ||
999 | picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0); | ||
1000 | if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) { | ||
1001 | /* Switch Cr and Cb for YVU420 format */ | ||
1002 | picture_cr = picture_y + stridey * height; | ||
1003 | picture_cb = picture_cr + stridey / 2 * height / 2; | ||
1004 | } else { | ||
1005 | picture_cb = picture_y + stridey * height; | ||
1006 | picture_cr = picture_cb + stridey / 2 * height / 2; | ||
1007 | } | ||
1008 | coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y); | ||
1009 | coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB); | ||
1010 | coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR); | ||
1011 | coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE); | ||
1012 | coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, | ||
1013 | CODA_CMD_DEC_PIC_ROT_MODE); | ||
1014 | |||
1015 | switch (dev->devtype->product) { | ||
1016 | case CODA_DX6: | ||
1017 | /* TBD */ | ||
1018 | case CODA_7541: | ||
1019 | coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION); | ||
1020 | break; | ||
1021 | } | ||
1022 | |||
1023 | coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM); | ||
1024 | |||
1025 | coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START); | ||
1026 | coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE); | ||
1027 | |||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | static void coda_prepare_encode(struct coda_ctx *ctx) | ||
673 | { | 1032 | { |
674 | struct coda_ctx *ctx = m2m_priv; | ||
675 | struct coda_q_data *q_data_src, *q_data_dst; | 1033 | struct coda_q_data *q_data_src, *q_data_dst; |
676 | struct vb2_buffer *src_buf, *dst_buf; | 1034 | struct vb2_buffer *src_buf, *dst_buf; |
677 | struct coda_dev *dev = ctx->dev; | 1035 | struct coda_dev *dev = ctx->dev; |
@@ -681,17 +1039,15 @@ static void coda_device_run(void *m2m_priv) | |||
681 | u32 pic_stream_buffer_addr, pic_stream_buffer_size; | 1039 | u32 pic_stream_buffer_addr, pic_stream_buffer_size; |
682 | u32 dst_fourcc; | 1040 | u32 dst_fourcc; |
683 | 1041 | ||
684 | mutex_lock(&dev->coda_mutex); | ||
685 | |||
686 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | 1042 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); |
687 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 1043 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
688 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 1044 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
689 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 1045 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
690 | dst_fourcc = q_data_dst->fourcc; | 1046 | dst_fourcc = q_data_dst->fourcc; |
691 | 1047 | ||
692 | src_buf->v4l2_buf.sequence = ctx->isequence; | 1048 | src_buf->v4l2_buf.sequence = ctx->osequence; |
693 | dst_buf->v4l2_buf.sequence = ctx->isequence; | 1049 | dst_buf->v4l2_buf.sequence = ctx->osequence; |
694 | ctx->isequence++; | 1050 | ctx->osequence++; |
695 | 1051 | ||
696 | /* | 1052 | /* |
697 | * Workaround coda firmware BUG that only marks the first | 1053 | * Workaround coda firmware BUG that only marks the first |
@@ -793,16 +1149,53 @@ static void coda_device_run(void *m2m_priv) | |||
793 | coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); | 1149 | coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); |
794 | coda_write(dev, pic_stream_buffer_size / 1024, | 1150 | coda_write(dev, pic_stream_buffer_size / 1024, |
795 | CODA_CMD_ENC_PIC_BB_SIZE); | 1151 | CODA_CMD_ENC_PIC_BB_SIZE); |
1152 | } | ||
796 | 1153 | ||
797 | if (dev->devtype->product == CODA_7541) { | 1154 | static void coda_device_run(void *m2m_priv) |
798 | coda_write(dev, CODA7_USE_BIT_ENABLE | CODA7_USE_HOST_BIT_ENABLE | | 1155 | { |
799 | CODA7_USE_ME_ENABLE | CODA7_USE_HOST_ME_ENABLE, | 1156 | struct coda_ctx *ctx = m2m_priv; |
800 | CODA7_REG_BIT_AXI_SRAM_USE); | 1157 | struct coda_dev *dev = ctx->dev; |
1158 | int ret; | ||
1159 | |||
1160 | mutex_lock(&ctx->buffer_mutex); | ||
1161 | |||
1162 | /* | ||
1163 | * If streamoff dequeued all buffers before we could get the lock, | ||
1164 | * just bail out immediately. | ||
1165 | */ | ||
1166 | if ((!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) && | ||
1167 | ctx->inst_type != CODA_INST_DECODER) || | ||
1168 | !v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { | ||
1169 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
1170 | "%d: device_run without buffers\n", ctx->idx); | ||
1171 | mutex_unlock(&ctx->buffer_mutex); | ||
1172 | schedule_work(&ctx->skip_run); | ||
1173 | return; | ||
801 | } | 1174 | } |
802 | 1175 | ||
1176 | mutex_lock(&dev->coda_mutex); | ||
1177 | |||
1178 | if (ctx->inst_type == CODA_INST_DECODER) { | ||
1179 | ret = coda_prepare_decode(ctx); | ||
1180 | if (ret < 0) { | ||
1181 | mutex_unlock(&dev->coda_mutex); | ||
1182 | mutex_unlock(&ctx->buffer_mutex); | ||
1183 | /* job_finish scheduled by prepare_decode */ | ||
1184 | return; | ||
1185 | } | ||
1186 | } else { | ||
1187 | coda_prepare_encode(ctx); | ||
1188 | } | ||
1189 | |||
1190 | if (dev->devtype->product != CODA_DX6) | ||
1191 | coda_write(dev, ctx->iram_info.axi_sram_use, | ||
1192 | CODA7_REG_BIT_AXI_SRAM_USE); | ||
1193 | |||
803 | /* 1 second timeout in case CODA locks up */ | 1194 | /* 1 second timeout in case CODA locks up */ |
804 | schedule_delayed_work(&dev->timeout, HZ); | 1195 | schedule_delayed_work(&dev->timeout, HZ); |
805 | 1196 | ||
1197 | if (ctx->inst_type == CODA_INST_DECODER) | ||
1198 | coda_kfifo_sync_to_device_full(ctx); | ||
806 | coda_command_async(ctx, CODA_COMMAND_PIC_RUN); | 1199 | coda_command_async(ctx, CODA_COMMAND_PIC_RUN); |
807 | } | 1200 | } |
808 | 1201 | ||
@@ -812,15 +1205,32 @@ static int coda_job_ready(void *m2m_priv) | |||
812 | 1205 | ||
813 | /* | 1206 | /* |
814 | * For both 'P' and 'key' frame cases 1 picture | 1207 | * For both 'P' and 'key' frame cases 1 picture |
815 | * and 1 frame are needed. | 1208 | * and 1 frame are needed. In the decoder case, |
1209 | * the compressed frame can be in the bitstream. | ||
816 | */ | 1210 | */ |
817 | if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) || | 1211 | if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) && |
818 | !v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { | 1212 | ctx->inst_type != CODA_INST_DECODER) { |
819 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 1213 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
820 | "not ready: not enough video buffers.\n"); | 1214 | "not ready: not enough video buffers.\n"); |
821 | return 0; | 1215 | return 0; |
822 | } | 1216 | } |
823 | 1217 | ||
1218 | if (!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { | ||
1219 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
1220 | "not ready: not enough video capture buffers.\n"); | ||
1221 | return 0; | ||
1222 | } | ||
1223 | |||
1224 | if (ctx->prescan_failed || | ||
1225 | ((ctx->inst_type == CODA_INST_DECODER) && | ||
1226 | (coda_get_bitstream_payload(ctx) < 512) && | ||
1227 | !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { | ||
1228 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
1229 | "%d: not ready: not enough bitstream data.\n", | ||
1230 | ctx->idx); | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
824 | if (ctx->aborting) { | 1234 | if (ctx->aborting) { |
825 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 1235 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
826 | "not ready: aborting\n"); | 1236 | "not ready: aborting\n"); |
@@ -936,7 +1346,29 @@ static int coda_buf_prepare(struct vb2_buffer *vb) | |||
936 | static void coda_buf_queue(struct vb2_buffer *vb) | 1346 | static void coda_buf_queue(struct vb2_buffer *vb) |
937 | { | 1347 | { |
938 | struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | 1348 | struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); |
939 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | 1349 | struct coda_q_data *q_data; |
1350 | |||
1351 | q_data = get_q_data(ctx, vb->vb2_queue->type); | ||
1352 | |||
1353 | /* | ||
1354 | * In the decoder case, immediately try to copy the buffer into the | ||
1355 | * bitstream ringbuffer and mark it as ready to be dequeued. | ||
1356 | */ | ||
1357 | if (q_data->fourcc == V4L2_PIX_FMT_H264 && | ||
1358 | vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | ||
1359 | /* | ||
1360 | * For backwards compatiblity, queuing an empty buffer marks | ||
1361 | * the stream end | ||
1362 | */ | ||
1363 | if (vb2_get_plane_payload(vb, 0) == 0) | ||
1364 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | ||
1365 | mutex_lock(&ctx->bitstream_mutex); | ||
1366 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | ||
1367 | coda_fill_bitstream(ctx); | ||
1368 | mutex_unlock(&ctx->bitstream_mutex); | ||
1369 | } else { | ||
1370 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | ||
1371 | } | ||
940 | } | 1372 | } |
941 | 1373 | ||
942 | static void coda_wait_prepare(struct vb2_queue *q) | 1374 | static void coda_wait_prepare(struct vb2_queue *q) |
@@ -951,21 +1383,6 @@ static void coda_wait_finish(struct vb2_queue *q) | |||
951 | coda_lock(ctx); | 1383 | coda_lock(ctx); |
952 | } | 1384 | } |
953 | 1385 | ||
954 | static void coda_free_framebuffers(struct coda_ctx *ctx) | ||
955 | { | ||
956 | int i; | ||
957 | |||
958 | for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) { | ||
959 | if (ctx->internal_frames[i].vaddr) { | ||
960 | dma_free_coherent(&ctx->dev->plat_dev->dev, | ||
961 | ctx->internal_frames[i].size, | ||
962 | ctx->internal_frames[i].vaddr, | ||
963 | ctx->internal_frames[i].paddr); | ||
964 | ctx->internal_frames[i].vaddr = NULL; | ||
965 | } | ||
966 | } | ||
967 | } | ||
968 | |||
969 | static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) | 1386 | static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) |
970 | { | 1387 | { |
971 | struct coda_dev *dev = ctx->dev; | 1388 | struct coda_dev *dev = ctx->dev; |
@@ -977,29 +1394,69 @@ static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) | |||
977 | p[index ^ 1] = value; | 1394 | p[index ^ 1] = value; |
978 | } | 1395 | } |
979 | 1396 | ||
1397 | static int coda_alloc_aux_buf(struct coda_dev *dev, | ||
1398 | struct coda_aux_buf *buf, size_t size) | ||
1399 | { | ||
1400 | buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf->paddr, | ||
1401 | GFP_KERNEL); | ||
1402 | if (!buf->vaddr) | ||
1403 | return -ENOMEM; | ||
1404 | |||
1405 | buf->size = size; | ||
1406 | |||
1407 | return 0; | ||
1408 | } | ||
1409 | |||
1410 | static inline int coda_alloc_context_buf(struct coda_ctx *ctx, | ||
1411 | struct coda_aux_buf *buf, size_t size) | ||
1412 | { | ||
1413 | return coda_alloc_aux_buf(ctx->dev, buf, size); | ||
1414 | } | ||
1415 | |||
1416 | static void coda_free_aux_buf(struct coda_dev *dev, | ||
1417 | struct coda_aux_buf *buf) | ||
1418 | { | ||
1419 | if (buf->vaddr) { | ||
1420 | dma_free_coherent(&dev->plat_dev->dev, buf->size, | ||
1421 | buf->vaddr, buf->paddr); | ||
1422 | buf->vaddr = NULL; | ||
1423 | buf->size = 0; | ||
1424 | } | ||
1425 | } | ||
1426 | |||
1427 | static void coda_free_framebuffers(struct coda_ctx *ctx) | ||
1428 | { | ||
1429 | int i; | ||
1430 | |||
1431 | for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) | ||
1432 | coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i]); | ||
1433 | } | ||
1434 | |||
980 | static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) | 1435 | static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) |
981 | { | 1436 | { |
982 | struct coda_dev *dev = ctx->dev; | 1437 | struct coda_dev *dev = ctx->dev; |
983 | |||
984 | int height = q_data->height; | 1438 | int height = q_data->height; |
985 | dma_addr_t paddr; | 1439 | dma_addr_t paddr; |
986 | int ysize; | 1440 | int ysize; |
1441 | int ret; | ||
987 | int i; | 1442 | int i; |
988 | 1443 | ||
1444 | if (ctx->codec && ctx->codec->src_fourcc == V4L2_PIX_FMT_H264) | ||
1445 | height = round_up(height, 16); | ||
989 | ysize = round_up(q_data->width, 8) * height; | 1446 | ysize = round_up(q_data->width, 8) * height; |
990 | 1447 | ||
991 | /* Allocate frame buffers */ | 1448 | /* Allocate frame buffers */ |
992 | ctx->num_internal_frames = CODA_MAX_FRAMEBUFFERS; | ||
993 | for (i = 0; i < ctx->num_internal_frames; i++) { | 1449 | for (i = 0; i < ctx->num_internal_frames; i++) { |
994 | ctx->internal_frames[i].size = q_data->sizeimage; | 1450 | size_t size; |
995 | if (fourcc == V4L2_PIX_FMT_H264 && dev->devtype->product != CODA_DX6) | 1451 | |
1452 | size = q_data->sizeimage; | ||
1453 | if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && | ||
1454 | dev->devtype->product != CODA_DX6) | ||
996 | ctx->internal_frames[i].size += ysize/4; | 1455 | ctx->internal_frames[i].size += ysize/4; |
997 | ctx->internal_frames[i].vaddr = dma_alloc_coherent( | 1456 | ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], size); |
998 | &dev->plat_dev->dev, ctx->internal_frames[i].size, | 1457 | if (ret < 0) { |
999 | &ctx->internal_frames[i].paddr, GFP_KERNEL); | ||
1000 | if (!ctx->internal_frames[i].vaddr) { | ||
1001 | coda_free_framebuffers(ctx); | 1458 | coda_free_framebuffers(ctx); |
1002 | return -ENOMEM; | 1459 | return ret; |
1003 | } | 1460 | } |
1004 | } | 1461 | } |
1005 | 1462 | ||
@@ -1010,10 +1467,20 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d | |||
1010 | coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */ | 1467 | coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */ |
1011 | coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + ysize/4); /* Cr */ | 1468 | coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + ysize/4); /* Cr */ |
1012 | 1469 | ||
1013 | if (dev->devtype->product != CODA_DX6 && fourcc == V4L2_PIX_FMT_H264) | 1470 | /* mvcol buffer for h.264 */ |
1014 | coda_parabuf_write(ctx, 96 + i, ctx->internal_frames[i].paddr + ysize + ysize/4 + ysize/4); | 1471 | if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && |
1472 | dev->devtype->product != CODA_DX6) | ||
1473 | coda_parabuf_write(ctx, 96 + i, | ||
1474 | ctx->internal_frames[i].paddr + | ||
1475 | ysize + ysize/4 + ysize/4); | ||
1015 | } | 1476 | } |
1016 | 1477 | ||
1478 | /* mvcol buffer for mpeg4 */ | ||
1479 | if ((dev->devtype->product != CODA_DX6) && | ||
1480 | (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4)) | ||
1481 | coda_parabuf_write(ctx, 97, ctx->internal_frames[i].paddr + | ||
1482 | ysize + ysize/4 + ysize/4); | ||
1483 | |||
1017 | return 0; | 1484 | return 0; |
1018 | } | 1485 | } |
1019 | 1486 | ||
@@ -1035,6 +1502,371 @@ static int coda_h264_padding(int size, char *p) | |||
1035 | return nal_size; | 1502 | return nal_size; |
1036 | } | 1503 | } |
1037 | 1504 | ||
1505 | static void coda_setup_iram(struct coda_ctx *ctx) | ||
1506 | { | ||
1507 | struct coda_iram_info *iram_info = &ctx->iram_info; | ||
1508 | struct coda_dev *dev = ctx->dev; | ||
1509 | int ipacdc_size; | ||
1510 | int bitram_size; | ||
1511 | int dbk_size; | ||
1512 | int ovl_size; | ||
1513 | int mb_width; | ||
1514 | int me_size; | ||
1515 | int size; | ||
1516 | |||
1517 | memset(iram_info, 0, sizeof(*iram_info)); | ||
1518 | size = dev->iram_size; | ||
1519 | |||
1520 | if (dev->devtype->product == CODA_DX6) | ||
1521 | return; | ||
1522 | |||
1523 | if (ctx->inst_type == CODA_INST_ENCODER) { | ||
1524 | struct coda_q_data *q_data_src; | ||
1525 | |||
1526 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
1527 | mb_width = DIV_ROUND_UP(q_data_src->width, 16); | ||
1528 | |||
1529 | /* Prioritize in case IRAM is too small for everything */ | ||
1530 | me_size = round_up(round_up(q_data_src->width, 16) * 36 + 2048, | ||
1531 | 1024); | ||
1532 | iram_info->search_ram_size = me_size; | ||
1533 | if (size >= iram_info->search_ram_size) { | ||
1534 | if (dev->devtype->product == CODA_7541) | ||
1535 | iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE; | ||
1536 | iram_info->search_ram_paddr = dev->iram_paddr; | ||
1537 | size -= iram_info->search_ram_size; | ||
1538 | } else { | ||
1539 | pr_err("IRAM is smaller than the search ram size\n"); | ||
1540 | goto out; | ||
1541 | } | ||
1542 | |||
1543 | /* Only H.264BP and H.263P3 are considered */ | ||
1544 | dbk_size = round_up(128 * mb_width, 1024); | ||
1545 | if (size >= dbk_size) { | ||
1546 | iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE; | ||
1547 | iram_info->buf_dbk_y_use = dev->iram_paddr + | ||
1548 | iram_info->search_ram_size; | ||
1549 | iram_info->buf_dbk_c_use = iram_info->buf_dbk_y_use + | ||
1550 | dbk_size / 2; | ||
1551 | size -= dbk_size; | ||
1552 | } else { | ||
1553 | goto out; | ||
1554 | } | ||
1555 | |||
1556 | bitram_size = round_up(128 * mb_width, 1024); | ||
1557 | if (size >= bitram_size) { | ||
1558 | iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE; | ||
1559 | iram_info->buf_bit_use = iram_info->buf_dbk_c_use + | ||
1560 | dbk_size / 2; | ||
1561 | size -= bitram_size; | ||
1562 | } else { | ||
1563 | goto out; | ||
1564 | } | ||
1565 | |||
1566 | ipacdc_size = round_up(128 * mb_width, 1024); | ||
1567 | if (size >= ipacdc_size) { | ||
1568 | iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE; | ||
1569 | iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use + | ||
1570 | bitram_size; | ||
1571 | size -= ipacdc_size; | ||
1572 | } | ||
1573 | |||
1574 | /* OVL and BTP disabled for encoder */ | ||
1575 | } else if (ctx->inst_type == CODA_INST_DECODER) { | ||
1576 | struct coda_q_data *q_data_dst; | ||
1577 | int mb_height; | ||
1578 | |||
1579 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
1580 | mb_width = DIV_ROUND_UP(q_data_dst->width, 16); | ||
1581 | mb_height = DIV_ROUND_UP(q_data_dst->height, 16); | ||
1582 | |||
1583 | dbk_size = round_up(256 * mb_width, 1024); | ||
1584 | if (size >= dbk_size) { | ||
1585 | iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE; | ||
1586 | iram_info->buf_dbk_y_use = dev->iram_paddr; | ||
1587 | iram_info->buf_dbk_c_use = dev->iram_paddr + | ||
1588 | dbk_size / 2; | ||
1589 | size -= dbk_size; | ||
1590 | } else { | ||
1591 | goto out; | ||
1592 | } | ||
1593 | |||
1594 | bitram_size = round_up(128 * mb_width, 1024); | ||
1595 | if (size >= bitram_size) { | ||
1596 | iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE; | ||
1597 | iram_info->buf_bit_use = iram_info->buf_dbk_c_use + | ||
1598 | dbk_size / 2; | ||
1599 | size -= bitram_size; | ||
1600 | } else { | ||
1601 | goto out; | ||
1602 | } | ||
1603 | |||
1604 | ipacdc_size = round_up(128 * mb_width, 1024); | ||
1605 | if (size >= ipacdc_size) { | ||
1606 | iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE; | ||
1607 | iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use + | ||
1608 | bitram_size; | ||
1609 | size -= ipacdc_size; | ||
1610 | } else { | ||
1611 | goto out; | ||
1612 | } | ||
1613 | |||
1614 | ovl_size = round_up(80 * mb_width, 1024); | ||
1615 | } | ||
1616 | |||
1617 | out: | ||
1618 | switch (dev->devtype->product) { | ||
1619 | case CODA_DX6: | ||
1620 | break; | ||
1621 | case CODA_7541: | ||
1622 | /* i.MX53 uses secondary AXI for IRAM access */ | ||
1623 | if (iram_info->axi_sram_use & CODA7_USE_HOST_BIT_ENABLE) | ||
1624 | iram_info->axi_sram_use |= CODA7_USE_BIT_ENABLE; | ||
1625 | if (iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE) | ||
1626 | iram_info->axi_sram_use |= CODA7_USE_IP_ENABLE; | ||
1627 | if (iram_info->axi_sram_use & CODA7_USE_HOST_DBK_ENABLE) | ||
1628 | iram_info->axi_sram_use |= CODA7_USE_DBK_ENABLE; | ||
1629 | if (iram_info->axi_sram_use & CODA7_USE_HOST_OVL_ENABLE) | ||
1630 | iram_info->axi_sram_use |= CODA7_USE_OVL_ENABLE; | ||
1631 | if (iram_info->axi_sram_use & CODA7_USE_HOST_ME_ENABLE) | ||
1632 | iram_info->axi_sram_use |= CODA7_USE_ME_ENABLE; | ||
1633 | } | ||
1634 | |||
1635 | if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)) | ||
1636 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
1637 | "IRAM smaller than needed\n"); | ||
1638 | |||
1639 | if (dev->devtype->product == CODA_7541) { | ||
1640 | /* TODO - Enabling these causes picture errors on CODA7541 */ | ||
1641 | if (ctx->inst_type == CODA_INST_DECODER) { | ||
1642 | /* fw 1.4.50 */ | ||
1643 | iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE | | ||
1644 | CODA7_USE_IP_ENABLE); | ||
1645 | } else { | ||
1646 | /* fw 13.4.29 */ | ||
1647 | iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE | | ||
1648 | CODA7_USE_HOST_DBK_ENABLE | | ||
1649 | CODA7_USE_IP_ENABLE | | ||
1650 | CODA7_USE_DBK_ENABLE); | ||
1651 | } | ||
1652 | } | ||
1653 | } | ||
1654 | |||
1655 | static void coda_free_context_buffers(struct coda_ctx *ctx) | ||
1656 | { | ||
1657 | struct coda_dev *dev = ctx->dev; | ||
1658 | |||
1659 | coda_free_aux_buf(dev, &ctx->slicebuf); | ||
1660 | coda_free_aux_buf(dev, &ctx->psbuf); | ||
1661 | if (dev->devtype->product != CODA_DX6) | ||
1662 | coda_free_aux_buf(dev, &ctx->workbuf); | ||
1663 | } | ||
1664 | |||
1665 | static int coda_alloc_context_buffers(struct coda_ctx *ctx, | ||
1666 | struct coda_q_data *q_data) | ||
1667 | { | ||
1668 | struct coda_dev *dev = ctx->dev; | ||
1669 | size_t size; | ||
1670 | int ret; | ||
1671 | |||
1672 | switch (dev->devtype->product) { | ||
1673 | case CODA_7541: | ||
1674 | size = CODA7_WORK_BUF_SIZE; | ||
1675 | break; | ||
1676 | default: | ||
1677 | return 0; | ||
1678 | } | ||
1679 | |||
1680 | if (ctx->psbuf.vaddr) { | ||
1681 | v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n"); | ||
1682 | return -EBUSY; | ||
1683 | } | ||
1684 | if (ctx->slicebuf.vaddr) { | ||
1685 | v4l2_err(&dev->v4l2_dev, "slicebuf still allocated\n"); | ||
1686 | return -EBUSY; | ||
1687 | } | ||
1688 | if (ctx->workbuf.vaddr) { | ||
1689 | v4l2_err(&dev->v4l2_dev, "context buffer still allocated\n"); | ||
1690 | ret = -EBUSY; | ||
1691 | return -ENOMEM; | ||
1692 | } | ||
1693 | |||
1694 | if (q_data->fourcc == V4L2_PIX_FMT_H264) { | ||
1695 | /* worst case slice size */ | ||
1696 | size = (DIV_ROUND_UP(q_data->width, 16) * | ||
1697 | DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512; | ||
1698 | ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size); | ||
1699 | if (ret < 0) { | ||
1700 | v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte slice buffer", | ||
1701 | ctx->slicebuf.size); | ||
1702 | return ret; | ||
1703 | } | ||
1704 | } | ||
1705 | |||
1706 | if (dev->devtype->product == CODA_7541) { | ||
1707 | ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE); | ||
1708 | if (ret < 0) { | ||
1709 | v4l2_err(&dev->v4l2_dev, "failed to allocate psmem buffer"); | ||
1710 | goto err; | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1714 | ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size); | ||
1715 | if (ret < 0) { | ||
1716 | v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte context buffer", | ||
1717 | ctx->workbuf.size); | ||
1718 | goto err; | ||
1719 | } | ||
1720 | |||
1721 | return 0; | ||
1722 | |||
1723 | err: | ||
1724 | coda_free_context_buffers(ctx); | ||
1725 | return ret; | ||
1726 | } | ||
1727 | |||
1728 | static int coda_start_decoding(struct coda_ctx *ctx) | ||
1729 | { | ||
1730 | struct coda_q_data *q_data_src, *q_data_dst; | ||
1731 | u32 bitstream_buf, bitstream_size; | ||
1732 | struct coda_dev *dev = ctx->dev; | ||
1733 | int width, height; | ||
1734 | u32 src_fourcc; | ||
1735 | u32 val; | ||
1736 | int ret; | ||
1737 | |||
1738 | /* Start decoding */ | ||
1739 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
1740 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
1741 | bitstream_buf = ctx->bitstream.paddr; | ||
1742 | bitstream_size = ctx->bitstream.size; | ||
1743 | src_fourcc = q_data_src->fourcc; | ||
1744 | |||
1745 | coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); | ||
1746 | |||
1747 | /* Update coda bitstream read and write pointers from kfifo */ | ||
1748 | coda_kfifo_sync_to_device_full(ctx); | ||
1749 | |||
1750 | ctx->display_idx = -1; | ||
1751 | ctx->frm_dis_flg = 0; | ||
1752 | coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | ||
1753 | |||
1754 | coda_write(dev, CODA_BIT_DEC_SEQ_INIT_ESCAPE, | ||
1755 | CODA_REG_BIT_BIT_STREAM_PARAM); | ||
1756 | |||
1757 | coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START); | ||
1758 | coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE); | ||
1759 | val = 0; | ||
1760 | if (dev->devtype->product == CODA_7541) | ||
1761 | val |= CODA_REORDER_ENABLE; | ||
1762 | coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); | ||
1763 | |||
1764 | ctx->params.codec_mode = ctx->codec->mode; | ||
1765 | ctx->params.codec_mode_aux = 0; | ||
1766 | if (src_fourcc == V4L2_PIX_FMT_H264) { | ||
1767 | if (dev->devtype->product == CODA_7541) { | ||
1768 | coda_write(dev, ctx->psbuf.paddr, | ||
1769 | CODA_CMD_DEC_SEQ_PS_BB_START); | ||
1770 | coda_write(dev, (CODA7_PS_BUF_SIZE / 1024), | ||
1771 | CODA_CMD_DEC_SEQ_PS_BB_SIZE); | ||
1772 | } | ||
1773 | } | ||
1774 | |||
1775 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { | ||
1776 | v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); | ||
1777 | coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
1778 | return -ETIMEDOUT; | ||
1779 | } | ||
1780 | |||
1781 | /* Update kfifo out pointer from coda bitstream read pointer */ | ||
1782 | coda_kfifo_sync_from_device(ctx); | ||
1783 | |||
1784 | coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
1785 | |||
1786 | if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) { | ||
1787 | v4l2_err(&dev->v4l2_dev, | ||
1788 | "CODA_COMMAND_SEQ_INIT failed, error code = %d\n", | ||
1789 | coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON)); | ||
1790 | return -EAGAIN; | ||
1791 | } | ||
1792 | |||
1793 | val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE); | ||
1794 | if (dev->devtype->product == CODA_DX6) { | ||
1795 | width = (val >> CODADX6_PICWIDTH_OFFSET) & CODADX6_PICWIDTH_MASK; | ||
1796 | height = val & CODADX6_PICHEIGHT_MASK; | ||
1797 | } else { | ||
1798 | width = (val >> CODA7_PICWIDTH_OFFSET) & CODA7_PICWIDTH_MASK; | ||
1799 | height = val & CODA7_PICHEIGHT_MASK; | ||
1800 | } | ||
1801 | |||
1802 | if (width > q_data_dst->width || height > q_data_dst->height) { | ||
1803 | v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n", | ||
1804 | width, height, q_data_dst->width, q_data_dst->height); | ||
1805 | return -EINVAL; | ||
1806 | } | ||
1807 | |||
1808 | width = round_up(width, 16); | ||
1809 | height = round_up(height, 16); | ||
1810 | |||
1811 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: %dx%d\n", | ||
1812 | __func__, ctx->idx, width, height); | ||
1813 | |||
1814 | ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED) + 1; | ||
1815 | if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) { | ||
1816 | v4l2_err(&dev->v4l2_dev, | ||
1817 | "not enough framebuffers to decode (%d < %d)\n", | ||
1818 | CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames); | ||
1819 | return -EINVAL; | ||
1820 | } | ||
1821 | |||
1822 | ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); | ||
1823 | if (ret < 0) | ||
1824 | return ret; | ||
1825 | |||
1826 | /* Tell the decoder how many frame buffers we allocated. */ | ||
1827 | coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); | ||
1828 | coda_write(dev, width, CODA_CMD_SET_FRAME_BUF_STRIDE); | ||
1829 | |||
1830 | if (dev->devtype->product != CODA_DX6) { | ||
1831 | /* Set secondary AXI IRAM */ | ||
1832 | coda_setup_iram(ctx); | ||
1833 | |||
1834 | coda_write(dev, ctx->iram_info.buf_bit_use, | ||
1835 | CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); | ||
1836 | coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, | ||
1837 | CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); | ||
1838 | coda_write(dev, ctx->iram_info.buf_dbk_y_use, | ||
1839 | CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); | ||
1840 | coda_write(dev, ctx->iram_info.buf_dbk_c_use, | ||
1841 | CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); | ||
1842 | coda_write(dev, ctx->iram_info.buf_ovl_use, | ||
1843 | CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); | ||
1844 | } | ||
1845 | |||
1846 | if (src_fourcc == V4L2_PIX_FMT_H264) { | ||
1847 | coda_write(dev, ctx->slicebuf.paddr, | ||
1848 | CODA_CMD_SET_FRAME_SLICE_BB_START); | ||
1849 | coda_write(dev, ctx->slicebuf.size / 1024, | ||
1850 | CODA_CMD_SET_FRAME_SLICE_BB_SIZE); | ||
1851 | } | ||
1852 | |||
1853 | if (dev->devtype->product == CODA_7541) { | ||
1854 | int max_mb_x = 1920 / 16; | ||
1855 | int max_mb_y = 1088 / 16; | ||
1856 | int max_mb_num = max_mb_x * max_mb_y; | ||
1857 | coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, | ||
1858 | CODA7_CMD_SET_FRAME_MAX_DEC_SIZE); | ||
1859 | } | ||
1860 | |||
1861 | if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { | ||
1862 | v4l2_err(&ctx->dev->v4l2_dev, | ||
1863 | "CODA_COMMAND_SET_FRAME_BUF timeout\n"); | ||
1864 | return -ETIMEDOUT; | ||
1865 | } | ||
1866 | |||
1867 | return 0; | ||
1868 | } | ||
1869 | |||
1038 | static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, | 1870 | static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, |
1039 | int header_code, u8 *header, int *size) | 1871 | int header_code, u8 *header, int *size) |
1040 | { | 1872 | { |
@@ -1050,7 +1882,7 @@ static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, | |||
1050 | v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); | 1882 | v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); |
1051 | return ret; | 1883 | return ret; |
1052 | } | 1884 | } |
1053 | *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - | 1885 | *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - |
1054 | coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); | 1886 | coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); |
1055 | memcpy(header, vb2_plane_vaddr(buf, 0), *size); | 1887 | memcpy(header, vb2_plane_vaddr(buf, 0), *size); |
1056 | 1888 | ||
@@ -1069,26 +1901,36 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1069 | u32 value; | 1901 | u32 value; |
1070 | int ret = 0; | 1902 | int ret = 0; |
1071 | 1903 | ||
1072 | if (count < 1) | 1904 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
1073 | return -EINVAL; | 1905 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { |
1906 | if (q_data_src->fourcc == V4L2_PIX_FMT_H264) { | ||
1907 | if (coda_get_bitstream_payload(ctx) < 512) | ||
1908 | return -EINVAL; | ||
1909 | } else { | ||
1910 | if (count < 1) | ||
1911 | return -EINVAL; | ||
1912 | } | ||
1074 | 1913 | ||
1075 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
1076 | ctx->streamon_out = 1; | 1914 | ctx->streamon_out = 1; |
1077 | else | ||
1078 | ctx->streamon_cap = 1; | ||
1079 | 1915 | ||
1080 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
1081 | if (ctx->streamon_out) { | ||
1082 | if (coda_format_is_yuv(q_data_src->fourcc)) | 1916 | if (coda_format_is_yuv(q_data_src->fourcc)) |
1083 | ctx->inst_type = CODA_INST_ENCODER; | 1917 | ctx->inst_type = CODA_INST_ENCODER; |
1084 | else | 1918 | else |
1085 | ctx->inst_type = CODA_INST_DECODER; | 1919 | ctx->inst_type = CODA_INST_DECODER; |
1920 | } else { | ||
1921 | if (count < 1) | ||
1922 | return -EINVAL; | ||
1923 | |||
1924 | ctx->streamon_cap = 1; | ||
1086 | } | 1925 | } |
1087 | 1926 | ||
1088 | /* Don't start the coda unless both queues are on */ | 1927 | /* Don't start the coda unless both queues are on */ |
1089 | if (!(ctx->streamon_out & ctx->streamon_cap)) | 1928 | if (!(ctx->streamon_out & ctx->streamon_cap)) |
1090 | return 0; | 1929 | return 0; |
1091 | 1930 | ||
1931 | /* Allow device_run with no buffers queued and after streamoff */ | ||
1932 | v4l2_m2m_set_src_buffered(ctx->m2m_ctx, true); | ||
1933 | |||
1092 | ctx->gopcounter = ctx->params.gop_size - 1; | 1934 | ctx->gopcounter = ctx->params.gop_size - 1; |
1093 | buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 1935 | buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
1094 | bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); | 1936 | bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); |
@@ -1103,6 +1945,25 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1103 | return -EINVAL; | 1945 | return -EINVAL; |
1104 | } | 1946 | } |
1105 | 1947 | ||
1948 | /* Allocate per-instance buffers */ | ||
1949 | ret = coda_alloc_context_buffers(ctx, q_data_src); | ||
1950 | if (ret < 0) | ||
1951 | return ret; | ||
1952 | |||
1953 | if (ctx->inst_type == CODA_INST_DECODER) { | ||
1954 | mutex_lock(&dev->coda_mutex); | ||
1955 | ret = coda_start_decoding(ctx); | ||
1956 | mutex_unlock(&dev->coda_mutex); | ||
1957 | if (ret == -EAGAIN) { | ||
1958 | return 0; | ||
1959 | } else if (ret < 0) { | ||
1960 | return ret; | ||
1961 | } else { | ||
1962 | ctx->initialized = 1; | ||
1963 | return 0; | ||
1964 | } | ||
1965 | } | ||
1966 | |||
1106 | if (!coda_is_initialized(dev)) { | 1967 | if (!coda_is_initialized(dev)) { |
1107 | v4l2_err(v4l2_dev, "coda is not initialized.\n"); | 1968 | v4l2_err(v4l2_dev, "coda is not initialized.\n"); |
1108 | return -EFAULT; | 1969 | return -EFAULT; |
@@ -1111,8 +1972,8 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1111 | mutex_lock(&dev->coda_mutex); | 1972 | mutex_lock(&dev->coda_mutex); |
1112 | 1973 | ||
1113 | coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); | 1974 | coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); |
1114 | coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->idx)); | 1975 | coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); |
1115 | coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->idx)); | 1976 | coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); |
1116 | switch (dev->devtype->product) { | 1977 | switch (dev->devtype->product) { |
1117 | case CODA_DX6: | 1978 | case CODA_DX6: |
1118 | coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | | 1979 | coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | |
@@ -1207,6 +2068,8 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1207 | } | 2068 | } |
1208 | coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); | 2069 | coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); |
1209 | 2070 | ||
2071 | coda_setup_iram(ctx); | ||
2072 | |||
1210 | if (dst_fourcc == V4L2_PIX_FMT_H264) { | 2073 | if (dst_fourcc == V4L2_PIX_FMT_H264) { |
1211 | value = (FMO_SLICE_SAVE_BUF_SIZE << 7); | 2074 | value = (FMO_SLICE_SAVE_BUF_SIZE << 7); |
1212 | value |= (0 & CODA_FMOPARAM_TYPE_MASK) << CODA_FMOPARAM_TYPE_OFFSET; | 2075 | value |= (0 & CODA_FMOPARAM_TYPE_MASK) << CODA_FMOPARAM_TYPE_OFFSET; |
@@ -1214,8 +2077,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1214 | if (dev->devtype->product == CODA_DX6) { | 2077 | if (dev->devtype->product == CODA_DX6) { |
1215 | coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); | 2078 | coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); |
1216 | } else { | 2079 | } else { |
1217 | coda_write(dev, dev->iram_paddr, CODA7_CMD_ENC_SEQ_SEARCH_BASE); | 2080 | coda_write(dev, ctx->iram_info.search_ram_paddr, |
1218 | coda_write(dev, 48 * 1024, CODA7_CMD_ENC_SEQ_SEARCH_SIZE); | 2081 | CODA7_CMD_ENC_SEQ_SEARCH_BASE); |
2082 | coda_write(dev, ctx->iram_info.search_ram_size, | ||
2083 | CODA7_CMD_ENC_SEQ_SEARCH_SIZE); | ||
1219 | } | 2084 | } |
1220 | } | 2085 | } |
1221 | 2086 | ||
@@ -1231,6 +2096,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1231 | goto out; | 2096 | goto out; |
1232 | } | 2097 | } |
1233 | 2098 | ||
2099 | ctx->num_internal_frames = 2; | ||
1234 | ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); | 2100 | ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); |
1235 | if (ret < 0) { | 2101 | if (ret < 0) { |
1236 | v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); | 2102 | v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); |
@@ -1239,13 +2105,20 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1239 | 2105 | ||
1240 | coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); | 2106 | coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); |
1241 | coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); | 2107 | coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); |
2108 | if (dev->devtype->product == CODA_7541) | ||
2109 | coda_write(dev, round_up(q_data_src->width, 8), | ||
2110 | CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); | ||
1242 | if (dev->devtype->product != CODA_DX6) { | 2111 | if (dev->devtype->product != CODA_DX6) { |
1243 | coda_write(dev, round_up(q_data_src->width, 8), CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); | 2112 | coda_write(dev, ctx->iram_info.buf_bit_use, |
1244 | coda_write(dev, dev->iram_paddr + 48 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); | 2113 | CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); |
1245 | coda_write(dev, dev->iram_paddr + 53 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); | 2114 | coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, |
1246 | coda_write(dev, dev->iram_paddr + 58 * 1024, CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); | 2115 | CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); |
1247 | coda_write(dev, dev->iram_paddr + 68 * 1024, CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); | 2116 | coda_write(dev, ctx->iram_info.buf_dbk_y_use, |
1248 | coda_write(dev, 0x0, CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); | 2117 | CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); |
2118 | coda_write(dev, ctx->iram_info.buf_dbk_c_use, | ||
2119 | CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); | ||
2120 | coda_write(dev, ctx->iram_info.buf_ovl_use, | ||
2121 | CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); | ||
1249 | } | 2122 | } |
1250 | ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); | 2123 | ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); |
1251 | if (ret < 0) { | 2124 | if (ret < 0) { |
@@ -1326,32 +2199,26 @@ static int coda_stop_streaming(struct vb2_queue *q) | |||
1326 | struct coda_dev *dev = ctx->dev; | 2199 | struct coda_dev *dev = ctx->dev; |
1327 | 2200 | ||
1328 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | 2201 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { |
1329 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2202 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
1330 | "%s: output\n", __func__); | 2203 | "%s: output\n", __func__); |
1331 | ctx->streamon_out = 0; | 2204 | ctx->streamon_out = 0; |
2205 | |||
2206 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | ||
2207 | |||
2208 | ctx->isequence = 0; | ||
1332 | } else { | 2209 | } else { |
1333 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2210 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
1334 | "%s: capture\n", __func__); | 2211 | "%s: capture\n", __func__); |
1335 | ctx->streamon_cap = 0; | 2212 | ctx->streamon_cap = 0; |
1336 | } | ||
1337 | |||
1338 | /* Don't stop the coda unless both queues are off */ | ||
1339 | if (ctx->streamon_out || ctx->streamon_cap) | ||
1340 | return 0; | ||
1341 | 2213 | ||
1342 | cancel_delayed_work(&dev->timeout); | 2214 | ctx->osequence = 0; |
1343 | |||
1344 | mutex_lock(&dev->coda_mutex); | ||
1345 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
1346 | "%s: sent command 'SEQ_END' to coda\n", __func__); | ||
1347 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { | ||
1348 | v4l2_err(&dev->v4l2_dev, | ||
1349 | "CODA_COMMAND_SEQ_END failed\n"); | ||
1350 | return -ETIMEDOUT; | ||
1351 | } | 2215 | } |
1352 | mutex_unlock(&dev->coda_mutex); | ||
1353 | 2216 | ||
1354 | coda_free_framebuffers(ctx); | 2217 | if (!ctx->streamon_out && !ctx->streamon_cap) { |
2218 | kfifo_init(&ctx->bitstream_fifo, | ||
2219 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
2220 | ctx->runcounter = 0; | ||
2221 | } | ||
1355 | 2222 | ||
1356 | return 0; | 2223 | return 0; |
1357 | } | 2224 | } |
@@ -1511,23 +2378,41 @@ static int coda_open(struct file *file) | |||
1511 | { | 2378 | { |
1512 | struct coda_dev *dev = video_drvdata(file); | 2379 | struct coda_dev *dev = video_drvdata(file); |
1513 | struct coda_ctx *ctx = NULL; | 2380 | struct coda_ctx *ctx = NULL; |
1514 | int ret = 0; | 2381 | int ret; |
1515 | int idx; | 2382 | int idx; |
1516 | 2383 | ||
1517 | idx = coda_next_free_instance(dev); | ||
1518 | if (idx >= CODA_MAX_INSTANCES) | ||
1519 | return -EBUSY; | ||
1520 | set_bit(idx, &dev->instance_mask); | ||
1521 | |||
1522 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | 2384 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); |
1523 | if (!ctx) | 2385 | if (!ctx) |
1524 | return -ENOMEM; | 2386 | return -ENOMEM; |
1525 | 2387 | ||
2388 | idx = coda_next_free_instance(dev); | ||
2389 | if (idx >= CODA_MAX_INSTANCES) { | ||
2390 | ret = -EBUSY; | ||
2391 | goto err_coda_max; | ||
2392 | } | ||
2393 | set_bit(idx, &dev->instance_mask); | ||
2394 | |||
2395 | INIT_WORK(&ctx->skip_run, coda_skip_run); | ||
1526 | v4l2_fh_init(&ctx->fh, video_devdata(file)); | 2396 | v4l2_fh_init(&ctx->fh, video_devdata(file)); |
1527 | file->private_data = &ctx->fh; | 2397 | file->private_data = &ctx->fh; |
1528 | v4l2_fh_add(&ctx->fh); | 2398 | v4l2_fh_add(&ctx->fh); |
1529 | ctx->dev = dev; | 2399 | ctx->dev = dev; |
1530 | ctx->idx = idx; | 2400 | ctx->idx = idx; |
2401 | switch (dev->devtype->product) { | ||
2402 | case CODA_7541: | ||
2403 | ctx->reg_idx = 0; | ||
2404 | break; | ||
2405 | default: | ||
2406 | ctx->reg_idx = idx; | ||
2407 | } | ||
2408 | |||
2409 | ret = clk_prepare_enable(dev->clk_per); | ||
2410 | if (ret) | ||
2411 | goto err_clk_per; | ||
2412 | |||
2413 | ret = clk_prepare_enable(dev->clk_ahb); | ||
2414 | if (ret) | ||
2415 | goto err_clk_ahb; | ||
1531 | 2416 | ||
1532 | set_default_params(ctx); | 2417 | set_default_params(ctx); |
1533 | ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, | 2418 | ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, |
@@ -1537,39 +2422,62 @@ static int coda_open(struct file *file) | |||
1537 | 2422 | ||
1538 | v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", | 2423 | v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", |
1539 | __func__, ret); | 2424 | __func__, ret); |
1540 | goto err; | 2425 | goto err_ctx_init; |
1541 | } | 2426 | } |
1542 | ret = coda_ctrls_setup(ctx); | 2427 | ret = coda_ctrls_setup(ctx); |
1543 | if (ret) { | 2428 | if (ret) { |
1544 | v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); | 2429 | v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); |
1545 | goto err; | 2430 | goto err_ctrls_setup; |
1546 | } | 2431 | } |
1547 | 2432 | ||
1548 | ctx->fh.ctrl_handler = &ctx->ctrls; | 2433 | ctx->fh.ctrl_handler = &ctx->ctrls; |
1549 | 2434 | ||
1550 | ctx->parabuf.vaddr = dma_alloc_coherent(&dev->plat_dev->dev, | 2435 | ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE); |
1551 | CODA_PARA_BUF_SIZE, &ctx->parabuf.paddr, GFP_KERNEL); | 2436 | if (ret < 0) { |
1552 | if (!ctx->parabuf.vaddr) { | ||
1553 | v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); | 2437 | v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); |
2438 | goto err_dma_alloc; | ||
2439 | } | ||
2440 | |||
2441 | ctx->bitstream.size = CODA_MAX_FRAME_SIZE; | ||
2442 | ctx->bitstream.vaddr = dma_alloc_writecombine(&dev->plat_dev->dev, | ||
2443 | ctx->bitstream.size, &ctx->bitstream.paddr, GFP_KERNEL); | ||
2444 | if (!ctx->bitstream.vaddr) { | ||
2445 | v4l2_err(&dev->v4l2_dev, "failed to allocate bitstream ringbuffer"); | ||
1554 | ret = -ENOMEM; | 2446 | ret = -ENOMEM; |
1555 | goto err; | 2447 | goto err_dma_writecombine; |
1556 | } | 2448 | } |
2449 | kfifo_init(&ctx->bitstream_fifo, | ||
2450 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
2451 | mutex_init(&ctx->bitstream_mutex); | ||
2452 | mutex_init(&ctx->buffer_mutex); | ||
1557 | 2453 | ||
1558 | coda_lock(ctx); | 2454 | coda_lock(ctx); |
1559 | list_add(&ctx->list, &dev->instances); | 2455 | list_add(&ctx->list, &dev->instances); |
1560 | coda_unlock(ctx); | 2456 | coda_unlock(ctx); |
1561 | 2457 | ||
1562 | clk_prepare_enable(dev->clk_per); | ||
1563 | clk_prepare_enable(dev->clk_ahb); | ||
1564 | |||
1565 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Created instance %d (%p)\n", | 2458 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Created instance %d (%p)\n", |
1566 | ctx->idx, ctx); | 2459 | ctx->idx, ctx); |
1567 | 2460 | ||
1568 | return 0; | 2461 | return 0; |
1569 | 2462 | ||
1570 | err: | 2463 | err_dma_writecombine: |
2464 | coda_free_context_buffers(ctx); | ||
2465 | if (ctx->dev->devtype->product == CODA_DX6) | ||
2466 | coda_free_aux_buf(dev, &ctx->workbuf); | ||
2467 | coda_free_aux_buf(dev, &ctx->parabuf); | ||
2468 | err_dma_alloc: | ||
2469 | v4l2_ctrl_handler_free(&ctx->ctrls); | ||
2470 | err_ctrls_setup: | ||
2471 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | ||
2472 | err_ctx_init: | ||
2473 | clk_disable_unprepare(dev->clk_ahb); | ||
2474 | err_clk_ahb: | ||
2475 | clk_disable_unprepare(dev->clk_per); | ||
2476 | err_clk_per: | ||
1571 | v4l2_fh_del(&ctx->fh); | 2477 | v4l2_fh_del(&ctx->fh); |
1572 | v4l2_fh_exit(&ctx->fh); | 2478 | v4l2_fh_exit(&ctx->fh); |
2479 | clear_bit(ctx->idx, &dev->instance_mask); | ||
2480 | err_coda_max: | ||
1573 | kfree(ctx); | 2481 | kfree(ctx); |
1574 | return ret; | 2482 | return ret; |
1575 | } | 2483 | } |
@@ -1582,16 +2490,37 @@ static int coda_release(struct file *file) | |||
1582 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", | 2490 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", |
1583 | ctx); | 2491 | ctx); |
1584 | 2492 | ||
2493 | /* If this instance is running, call .job_abort and wait for it to end */ | ||
2494 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | ||
2495 | |||
2496 | /* In case the instance was not running, we still need to call SEQ_END */ | ||
2497 | mutex_lock(&dev->coda_mutex); | ||
2498 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
2499 | "%s: sent command 'SEQ_END' to coda\n", __func__); | ||
2500 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { | ||
2501 | v4l2_err(&dev->v4l2_dev, | ||
2502 | "CODA_COMMAND_SEQ_END failed\n"); | ||
2503 | mutex_unlock(&dev->coda_mutex); | ||
2504 | return -ETIMEDOUT; | ||
2505 | } | ||
2506 | mutex_unlock(&dev->coda_mutex); | ||
2507 | |||
2508 | coda_free_framebuffers(ctx); | ||
2509 | |||
1585 | coda_lock(ctx); | 2510 | coda_lock(ctx); |
1586 | list_del(&ctx->list); | 2511 | list_del(&ctx->list); |
1587 | coda_unlock(ctx); | 2512 | coda_unlock(ctx); |
1588 | 2513 | ||
1589 | dma_free_coherent(&dev->plat_dev->dev, CODA_PARA_BUF_SIZE, | 2514 | dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size, |
1590 | ctx->parabuf.vaddr, ctx->parabuf.paddr); | 2515 | ctx->bitstream.vaddr, ctx->bitstream.paddr); |
1591 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | 2516 | coda_free_context_buffers(ctx); |
2517 | if (ctx->dev->devtype->product == CODA_DX6) | ||
2518 | coda_free_aux_buf(dev, &ctx->workbuf); | ||
2519 | |||
2520 | coda_free_aux_buf(dev, &ctx->parabuf); | ||
1592 | v4l2_ctrl_handler_free(&ctx->ctrls); | 2521 | v4l2_ctrl_handler_free(&ctx->ctrls); |
1593 | clk_disable_unprepare(dev->clk_per); | ||
1594 | clk_disable_unprepare(dev->clk_ahb); | 2522 | clk_disable_unprepare(dev->clk_ahb); |
2523 | clk_disable_unprepare(dev->clk_per); | ||
1595 | v4l2_fh_del(&ctx->fh); | 2524 | v4l2_fh_del(&ctx->fh); |
1596 | v4l2_fh_exit(&ctx->fh); | 2525 | v4l2_fh_exit(&ctx->fh); |
1597 | clear_bit(ctx->idx, &dev->instance_mask); | 2526 | clear_bit(ctx->idx, &dev->instance_mask); |
@@ -1628,55 +2557,180 @@ static const struct v4l2_file_operations coda_fops = { | |||
1628 | .mmap = coda_mmap, | 2557 | .mmap = coda_mmap, |
1629 | }; | 2558 | }; |
1630 | 2559 | ||
1631 | static irqreturn_t coda_irq_handler(int irq, void *data) | 2560 | static void coda_finish_decode(struct coda_ctx *ctx) |
1632 | { | 2561 | { |
1633 | struct vb2_buffer *src_buf, *dst_buf; | 2562 | struct coda_dev *dev = ctx->dev; |
1634 | struct coda_dev *dev = data; | 2563 | struct coda_q_data *q_data_src; |
1635 | u32 wr_ptr, start_ptr; | 2564 | struct coda_q_data *q_data_dst; |
1636 | struct coda_ctx *ctx; | 2565 | struct vb2_buffer *dst_buf; |
2566 | int width, height; | ||
2567 | int decoded_idx; | ||
2568 | int display_idx; | ||
2569 | u32 src_fourcc; | ||
2570 | int success; | ||
2571 | u32 val; | ||
1637 | 2572 | ||
1638 | cancel_delayed_work(&dev->timeout); | 2573 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
1639 | 2574 | ||
1640 | /* read status register to attend the IRQ */ | 2575 | /* Update kfifo out pointer from coda bitstream read pointer */ |
1641 | coda_read(dev, CODA_REG_BIT_INT_STATUS); | 2576 | coda_kfifo_sync_from_device(ctx); |
1642 | coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, | ||
1643 | CODA_REG_BIT_INT_CLEAR); | ||
1644 | 2577 | ||
1645 | ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); | 2578 | /* |
1646 | if (ctx == NULL) { | 2579 | * in stream-end mode, the read pointer can overshoot the write pointer |
1647 | v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n"); | 2580 | * by up to 512 bytes |
1648 | mutex_unlock(&dev->coda_mutex); | 2581 | */ |
1649 | return IRQ_HANDLED; | 2582 | if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) { |
2583 | if (coda_get_bitstream_payload(ctx) >= 0x100000 - 512) | ||
2584 | kfifo_init(&ctx->bitstream_fifo, | ||
2585 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
1650 | } | 2586 | } |
1651 | 2587 | ||
1652 | if (ctx->aborting) { | 2588 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
1653 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2589 | src_fourcc = q_data_src->fourcc; |
1654 | "task has been aborted\n"); | 2590 | |
1655 | mutex_unlock(&dev->coda_mutex); | 2591 | val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS); |
1656 | return IRQ_HANDLED; | 2592 | if (val != 1) |
2593 | pr_err("DEC_PIC_SUCCESS = %d\n", val); | ||
2594 | |||
2595 | success = val & 0x1; | ||
2596 | if (!success) | ||
2597 | v4l2_err(&dev->v4l2_dev, "decode failed\n"); | ||
2598 | |||
2599 | if (src_fourcc == V4L2_PIX_FMT_H264) { | ||
2600 | if (val & (1 << 3)) | ||
2601 | v4l2_err(&dev->v4l2_dev, | ||
2602 | "insufficient PS buffer space (%d bytes)\n", | ||
2603 | ctx->psbuf.size); | ||
2604 | if (val & (1 << 2)) | ||
2605 | v4l2_err(&dev->v4l2_dev, | ||
2606 | "insufficient slice buffer space (%d bytes)\n", | ||
2607 | ctx->slicebuf.size); | ||
1657 | } | 2608 | } |
1658 | 2609 | ||
1659 | if (coda_isbusy(ctx->dev)) { | 2610 | val = coda_read(dev, CODA_RET_DEC_PIC_SIZE); |
1660 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2611 | width = (val >> 16) & 0xffff; |
1661 | "coda is still busy!!!!\n"); | 2612 | height = val & 0xffff; |
1662 | return IRQ_NONE; | 2613 | |
2614 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
2615 | |||
2616 | val = coda_read(dev, CODA_RET_DEC_PIC_TYPE); | ||
2617 | if ((val & 0x7) == 0) { | ||
2618 | dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; | ||
2619 | dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; | ||
2620 | } else { | ||
2621 | dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; | ||
2622 | dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; | ||
2623 | } | ||
2624 | |||
2625 | val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); | ||
2626 | if (val > 0) | ||
2627 | v4l2_err(&dev->v4l2_dev, | ||
2628 | "errors in %d macroblocks\n", val); | ||
2629 | |||
2630 | if (dev->devtype->product == CODA_7541) { | ||
2631 | val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); | ||
2632 | if (val == 0) { | ||
2633 | /* not enough bitstream data */ | ||
2634 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
2635 | "prescan failed: %d\n", val); | ||
2636 | ctx->prescan_failed = true; | ||
2637 | return; | ||
2638 | } | ||
2639 | } | ||
2640 | |||
2641 | ctx->frm_dis_flg = coda_read(dev, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | ||
2642 | |||
2643 | /* | ||
2644 | * The previous display frame was copied out by the rotator, | ||
2645 | * now it can be overwritten again | ||
2646 | */ | ||
2647 | if (ctx->display_idx >= 0 && | ||
2648 | ctx->display_idx < ctx->num_internal_frames) { | ||
2649 | ctx->frm_dis_flg &= ~(1 << ctx->display_idx); | ||
2650 | coda_write(dev, ctx->frm_dis_flg, | ||
2651 | CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | ||
2652 | } | ||
2653 | |||
2654 | /* | ||
2655 | * The index of the last decoded frame, not necessarily in | ||
2656 | * display order, and the index of the next display frame. | ||
2657 | * The latter could have been decoded in a previous run. | ||
2658 | */ | ||
2659 | decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX); | ||
2660 | display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX); | ||
2661 | |||
2662 | if (decoded_idx == -1) { | ||
2663 | /* no frame was decoded, but we might have a display frame */ | ||
2664 | if (display_idx < 0 && ctx->display_idx < 0) | ||
2665 | ctx->prescan_failed = true; | ||
2666 | } else if (decoded_idx == -2) { | ||
2667 | /* no frame was decoded, we still return the remaining buffers */ | ||
2668 | } else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) { | ||
2669 | v4l2_err(&dev->v4l2_dev, | ||
2670 | "decoded frame index out of range: %d\n", decoded_idx); | ||
1663 | } | 2671 | } |
1664 | 2672 | ||
2673 | if (display_idx == -1) { | ||
2674 | /* | ||
2675 | * no more frames to be decoded, but there could still | ||
2676 | * be rotator output to dequeue | ||
2677 | */ | ||
2678 | ctx->prescan_failed = true; | ||
2679 | } else if (display_idx == -3) { | ||
2680 | /* possibly prescan failure */ | ||
2681 | } else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) { | ||
2682 | v4l2_err(&dev->v4l2_dev, | ||
2683 | "presentation frame index out of range: %d\n", | ||
2684 | display_idx); | ||
2685 | } | ||
2686 | |||
2687 | /* If a frame was copied out, return it */ | ||
2688 | if (ctx->display_idx >= 0 && | ||
2689 | ctx->display_idx < ctx->num_internal_frames) { | ||
2690 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); | ||
2691 | dst_buf->v4l2_buf.sequence = ctx->osequence++; | ||
2692 | |||
2693 | vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); | ||
2694 | |||
2695 | v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE : | ||
2696 | VB2_BUF_STATE_ERROR); | ||
2697 | |||
2698 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
2699 | "job finished: decoding frame (%d) (%s)\n", | ||
2700 | dst_buf->v4l2_buf.sequence, | ||
2701 | (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? | ||
2702 | "KEYFRAME" : "PFRAME"); | ||
2703 | } else { | ||
2704 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
2705 | "job finished: no frame decoded\n"); | ||
2706 | } | ||
2707 | |||
2708 | /* The rotator will copy the current display frame next time */ | ||
2709 | ctx->display_idx = display_idx; | ||
2710 | } | ||
2711 | |||
2712 | static void coda_finish_encode(struct coda_ctx *ctx) | ||
2713 | { | ||
2714 | struct vb2_buffer *src_buf, *dst_buf; | ||
2715 | struct coda_dev *dev = ctx->dev; | ||
2716 | u32 wr_ptr, start_ptr; | ||
2717 | |||
1665 | src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); | 2718 | src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); |
1666 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); | 2719 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); |
1667 | 2720 | ||
1668 | /* Get results from the coda */ | 2721 | /* Get results from the coda */ |
1669 | coda_read(dev, CODA_RET_ENC_PIC_TYPE); | 2722 | coda_read(dev, CODA_RET_ENC_PIC_TYPE); |
1670 | start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); | 2723 | start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); |
1671 | wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)); | 2724 | wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); |
2725 | |||
1672 | /* Calculate bytesused field */ | 2726 | /* Calculate bytesused field */ |
1673 | if (dst_buf->v4l2_buf.sequence == 0) { | 2727 | if (dst_buf->v4l2_buf.sequence == 0) { |
1674 | dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr) + | 2728 | vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr + |
1675 | ctx->vpu_header_size[0] + | 2729 | ctx->vpu_header_size[0] + |
1676 | ctx->vpu_header_size[1] + | 2730 | ctx->vpu_header_size[1] + |
1677 | ctx->vpu_header_size[2]; | 2731 | ctx->vpu_header_size[2]); |
1678 | } else { | 2732 | } else { |
1679 | dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr); | 2733 | vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr); |
1680 | } | 2734 | } |
1681 | 2735 | ||
1682 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n", | 2736 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n", |
@@ -1708,8 +2762,62 @@ static irqreturn_t coda_irq_handler(int irq, void *data) | |||
1708 | dst_buf->v4l2_buf.sequence, | 2762 | dst_buf->v4l2_buf.sequence, |
1709 | (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? | 2763 | (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? |
1710 | "KEYFRAME" : "PFRAME"); | 2764 | "KEYFRAME" : "PFRAME"); |
2765 | } | ||
2766 | |||
2767 | static irqreturn_t coda_irq_handler(int irq, void *data) | ||
2768 | { | ||
2769 | struct coda_dev *dev = data; | ||
2770 | struct coda_ctx *ctx; | ||
2771 | |||
2772 | cancel_delayed_work(&dev->timeout); | ||
2773 | |||
2774 | /* read status register to attend the IRQ */ | ||
2775 | coda_read(dev, CODA_REG_BIT_INT_STATUS); | ||
2776 | coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, | ||
2777 | CODA_REG_BIT_INT_CLEAR); | ||
2778 | |||
2779 | ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); | ||
2780 | if (ctx == NULL) { | ||
2781 | v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n"); | ||
2782 | mutex_unlock(&dev->coda_mutex); | ||
2783 | return IRQ_HANDLED; | ||
2784 | } | ||
2785 | |||
2786 | if (ctx->aborting) { | ||
2787 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
2788 | "task has been aborted\n"); | ||
2789 | goto out; | ||
2790 | } | ||
2791 | |||
2792 | if (coda_isbusy(ctx->dev)) { | ||
2793 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
2794 | "coda is still busy!!!!\n"); | ||
2795 | return IRQ_NONE; | ||
2796 | } | ||
2797 | |||
2798 | if (ctx->inst_type == CODA_INST_DECODER) | ||
2799 | coda_finish_decode(ctx); | ||
2800 | else | ||
2801 | coda_finish_encode(ctx); | ||
2802 | |||
2803 | out: | ||
2804 | if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) { | ||
2805 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
2806 | "%s: sent command 'SEQ_END' to coda\n", __func__); | ||
2807 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { | ||
2808 | v4l2_err(&dev->v4l2_dev, | ||
2809 | "CODA_COMMAND_SEQ_END failed\n"); | ||
2810 | } | ||
2811 | |||
2812 | kfifo_init(&ctx->bitstream_fifo, | ||
2813 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
2814 | |||
2815 | coda_free_framebuffers(ctx); | ||
2816 | coda_free_context_buffers(ctx); | ||
2817 | } | ||
1711 | 2818 | ||
1712 | mutex_unlock(&dev->coda_mutex); | 2819 | mutex_unlock(&dev->coda_mutex); |
2820 | mutex_unlock(&ctx->buffer_mutex); | ||
1713 | 2821 | ||
1714 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); | 2822 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); |
1715 | 2823 | ||
@@ -1726,6 +2834,8 @@ static void coda_timeout(struct work_struct *work) | |||
1726 | 2834 | ||
1727 | mutex_lock(&dev->dev_mutex); | 2835 | mutex_lock(&dev->dev_mutex); |
1728 | list_for_each_entry(ctx, &dev->instances, list) { | 2836 | list_for_each_entry(ctx, &dev->instances, list) { |
2837 | if (mutex_is_locked(&ctx->buffer_mutex)) | ||
2838 | mutex_unlock(&ctx->buffer_mutex); | ||
1729 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 2839 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
1730 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 2840 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
1731 | } | 2841 | } |
@@ -1738,7 +2848,7 @@ static void coda_timeout(struct work_struct *work) | |||
1738 | 2848 | ||
1739 | static u32 coda_supported_firmwares[] = { | 2849 | static u32 coda_supported_firmwares[] = { |
1740 | CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), | 2850 | CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), |
1741 | CODA_FIRMWARE_VERNUM(CODA_7541, 13, 4, 29), | 2851 | CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50), |
1742 | }; | 2852 | }; |
1743 | 2853 | ||
1744 | static bool coda_firmware_supported(u32 vernum) | 2854 | static bool coda_firmware_supported(u32 vernum) |
@@ -1771,10 +2881,15 @@ static int coda_hw_init(struct coda_dev *dev) | |||
1771 | u16 product, major, minor, release; | 2881 | u16 product, major, minor, release; |
1772 | u32 data; | 2882 | u32 data; |
1773 | u16 *p; | 2883 | u16 *p; |
1774 | int i; | 2884 | int i, ret; |
1775 | 2885 | ||
1776 | clk_prepare_enable(dev->clk_per); | 2886 | ret = clk_prepare_enable(dev->clk_per); |
1777 | clk_prepare_enable(dev->clk_ahb); | 2887 | if (ret) |
2888 | return ret; | ||
2889 | |||
2890 | ret = clk_prepare_enable(dev->clk_ahb); | ||
2891 | if (ret) | ||
2892 | goto err_clk_ahb; | ||
1778 | 2893 | ||
1779 | /* | 2894 | /* |
1780 | * Copy the first CODA_ISRAM_SIZE in the internal SRAM. | 2895 | * Copy the first CODA_ISRAM_SIZE in the internal SRAM. |
@@ -1803,8 +2918,14 @@ static int coda_hw_init(struct coda_dev *dev) | |||
1803 | coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); | 2918 | coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); |
1804 | 2919 | ||
1805 | /* Tell the BIT where to find everything it needs */ | 2920 | /* Tell the BIT where to find everything it needs */ |
1806 | coda_write(dev, dev->workbuf.paddr, | 2921 | if (dev->devtype->product == CODA_7541) { |
1807 | CODA_REG_BIT_WORK_BUF_ADDR); | 2922 | coda_write(dev, dev->tempbuf.paddr, |
2923 | CODA_REG_BIT_TEMP_BUF_ADDR); | ||
2924 | coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
2925 | } else { | ||
2926 | coda_write(dev, dev->workbuf.paddr, | ||
2927 | CODA_REG_BIT_WORK_BUF_ADDR); | ||
2928 | } | ||
1808 | coda_write(dev, dev->codebuf.paddr, | 2929 | coda_write(dev, dev->codebuf.paddr, |
1809 | CODA_REG_BIT_CODE_BUF_ADDR); | 2930 | CODA_REG_BIT_CODE_BUF_ADDR); |
1810 | coda_write(dev, 0, CODA_REG_BIT_CODE_RUN); | 2931 | coda_write(dev, 0, CODA_REG_BIT_CODE_RUN); |
@@ -1877,6 +2998,10 @@ static int coda_hw_init(struct coda_dev *dev) | |||
1877 | } | 2998 | } |
1878 | 2999 | ||
1879 | return 0; | 3000 | return 0; |
3001 | |||
3002 | err_clk_ahb: | ||
3003 | clk_disable_unprepare(dev->clk_per); | ||
3004 | return ret; | ||
1880 | } | 3005 | } |
1881 | 3006 | ||
1882 | static void coda_fw_callback(const struct firmware *fw, void *context) | 3007 | static void coda_fw_callback(const struct firmware *fw, void *context) |
@@ -1891,11 +3016,8 @@ static void coda_fw_callback(const struct firmware *fw, void *context) | |||
1891 | } | 3016 | } |
1892 | 3017 | ||
1893 | /* allocate auxiliary per-device code buffer for the BIT processor */ | 3018 | /* allocate auxiliary per-device code buffer for the BIT processor */ |
1894 | dev->codebuf.size = fw->size; | 3019 | ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size); |
1895 | dev->codebuf.vaddr = dma_alloc_coherent(&pdev->dev, fw->size, | 3020 | if (ret < 0) { |
1896 | &dev->codebuf.paddr, | ||
1897 | GFP_KERNEL); | ||
1898 | if (!dev->codebuf.vaddr) { | ||
1899 | dev_err(&pdev->dev, "failed to allocate code buffer\n"); | 3021 | dev_err(&pdev->dev, "failed to allocate code buffer\n"); |
1900 | return; | 3022 | return; |
1901 | } | 3023 | } |
@@ -2032,11 +3154,6 @@ static int coda_probe(struct platform_device *pdev) | |||
2032 | 3154 | ||
2033 | /* Get memory for physical registers */ | 3155 | /* Get memory for physical registers */ |
2034 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 3156 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2035 | if (res == NULL) { | ||
2036 | dev_err(&pdev->dev, "failed to get memory region resource\n"); | ||
2037 | return -ENOENT; | ||
2038 | } | ||
2039 | |||
2040 | dev->regs_base = devm_ioremap_resource(&pdev->dev, res); | 3157 | dev->regs_base = devm_ioremap_resource(&pdev->dev, res); |
2041 | if (IS_ERR(dev->regs_base)) | 3158 | if (IS_ERR(dev->regs_base)) |
2042 | return PTR_ERR(dev->regs_base); | 3159 | return PTR_ERR(dev->regs_base); |
@@ -2048,8 +3165,8 @@ static int coda_probe(struct platform_device *pdev) | |||
2048 | return -ENOENT; | 3165 | return -ENOENT; |
2049 | } | 3166 | } |
2050 | 3167 | ||
2051 | if (devm_request_irq(&pdev->dev, irq, coda_irq_handler, | 3168 | if (devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler, |
2052 | 0, CODA_NAME, dev) < 0) { | 3169 | IRQF_ONESHOT, CODA_NAME, dev) < 0) { |
2053 | dev_err(&pdev->dev, "failed to request irq\n"); | 3170 | dev_err(&pdev->dev, "failed to request irq\n"); |
2054 | return -ENOENT; | 3171 | return -ENOENT; |
2055 | } | 3172 | } |
@@ -2085,24 +3202,36 @@ static int coda_probe(struct platform_device *pdev) | |||
2085 | /* allocate auxiliary per-device buffers for the BIT processor */ | 3202 | /* allocate auxiliary per-device buffers for the BIT processor */ |
2086 | switch (dev->devtype->product) { | 3203 | switch (dev->devtype->product) { |
2087 | case CODA_DX6: | 3204 | case CODA_DX6: |
2088 | dev->workbuf.size = CODADX6_WORK_BUF_SIZE; | 3205 | ret = coda_alloc_aux_buf(dev, &dev->workbuf, |
3206 | CODADX6_WORK_BUF_SIZE); | ||
3207 | if (ret < 0) { | ||
3208 | dev_err(&pdev->dev, "failed to allocate work buffer\n"); | ||
3209 | v4l2_device_unregister(&dev->v4l2_dev); | ||
3210 | return ret; | ||
3211 | } | ||
3212 | break; | ||
3213 | case CODA_7541: | ||
3214 | dev->tempbuf.size = CODA7_TEMP_BUF_SIZE; | ||
2089 | break; | 3215 | break; |
2090 | default: | ||
2091 | dev->workbuf.size = CODA7_WORK_BUF_SIZE; | ||
2092 | } | 3216 | } |
2093 | dev->workbuf.vaddr = dma_alloc_coherent(&pdev->dev, dev->workbuf.size, | 3217 | if (dev->tempbuf.size) { |
2094 | &dev->workbuf.paddr, | 3218 | ret = coda_alloc_aux_buf(dev, &dev->tempbuf, |
2095 | GFP_KERNEL); | 3219 | dev->tempbuf.size); |
2096 | if (!dev->workbuf.vaddr) { | 3220 | if (ret < 0) { |
2097 | dev_err(&pdev->dev, "failed to allocate work buffer\n"); | 3221 | dev_err(&pdev->dev, "failed to allocate temp buffer\n"); |
2098 | v4l2_device_unregister(&dev->v4l2_dev); | 3222 | v4l2_device_unregister(&dev->v4l2_dev); |
2099 | return -ENOMEM; | 3223 | return ret; |
3224 | } | ||
2100 | } | 3225 | } |
2101 | 3226 | ||
2102 | if (dev->devtype->product == CODA_DX6) | 3227 | switch (dev->devtype->product) { |
3228 | case CODA_DX6: | ||
2103 | dev->iram_size = CODADX6_IRAM_SIZE; | 3229 | dev->iram_size = CODADX6_IRAM_SIZE; |
2104 | else | 3230 | break; |
3231 | case CODA_7541: | ||
2105 | dev->iram_size = CODA7_IRAM_SIZE; | 3232 | dev->iram_size = CODA7_IRAM_SIZE; |
3233 | break; | ||
3234 | } | ||
2106 | dev->iram_vaddr = gen_pool_alloc(dev->iram_pool, dev->iram_size); | 3235 | dev->iram_vaddr = gen_pool_alloc(dev->iram_pool, dev->iram_size); |
2107 | if (!dev->iram_vaddr) { | 3236 | if (!dev->iram_vaddr) { |
2108 | dev_err(&pdev->dev, "unable to alloc iram\n"); | 3237 | dev_err(&pdev->dev, "unable to alloc iram\n"); |
@@ -2128,12 +3257,9 @@ static int coda_remove(struct platform_device *pdev) | |||
2128 | v4l2_device_unregister(&dev->v4l2_dev); | 3257 | v4l2_device_unregister(&dev->v4l2_dev); |
2129 | if (dev->iram_vaddr) | 3258 | if (dev->iram_vaddr) |
2130 | gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size); | 3259 | gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size); |
2131 | if (dev->codebuf.vaddr) | 3260 | coda_free_aux_buf(dev, &dev->codebuf); |
2132 | dma_free_coherent(&pdev->dev, dev->codebuf.size, | 3261 | coda_free_aux_buf(dev, &dev->tempbuf); |
2133 | &dev->codebuf.vaddr, dev->codebuf.paddr); | 3262 | coda_free_aux_buf(dev, &dev->workbuf); |
2134 | if (dev->workbuf.vaddr) | ||
2135 | dma_free_coherent(&pdev->dev, dev->workbuf.size, &dev->workbuf.vaddr, | ||
2136 | dev->workbuf.paddr); | ||
2137 | return 0; | 3263 | return 0; |
2138 | } | 3264 | } |
2139 | 3265 | ||
diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h index ace0bf0a3b9c..4e32e2edea62 100644 --- a/drivers/media/platform/coda.h +++ b/drivers/media/platform/coda.h | |||
@@ -43,14 +43,26 @@ | |||
43 | #define CODA_STREAM_ENDIAN_SELECT (1 << 0) | 43 | #define CODA_STREAM_ENDIAN_SELECT (1 << 0) |
44 | #define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 | 44 | #define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 |
45 | #define CODA_IMAGE_ENDIAN_SELECT (1 << 0) | 45 | #define CODA_IMAGE_ENDIAN_SELECT (1 << 0) |
46 | #define CODA_REG_BIT_BIT_STREAM_PARAM 0x114 | ||
47 | #define CODA_BIT_STREAM_END_FLAG (1 << 2) | ||
48 | #define CODA_BIT_DEC_SEQ_INIT_ESCAPE (1 << 0) | ||
49 | #define CODA_REG_BIT_TEMP_BUF_ADDR 0x118 | ||
46 | #define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x)) | 50 | #define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x)) |
47 | #define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x)) | 51 | #define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x)) |
52 | #define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x)) | ||
48 | #define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 | 53 | #define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 |
49 | #define CODA7_REG_BIT_AXI_SRAM_USE 0x140 | 54 | #define CODA7_REG_BIT_AXI_SRAM_USE 0x140 |
50 | #define CODA7_USE_BIT_ENABLE (1 << 0) | 55 | #define CODA7_USE_HOST_ME_ENABLE (1 << 11) |
56 | #define CODA7_USE_HOST_OVL_ENABLE (1 << 10) | ||
57 | #define CODA7_USE_HOST_DBK_ENABLE (1 << 9) | ||
58 | #define CODA7_USE_HOST_IP_ENABLE (1 << 8) | ||
51 | #define CODA7_USE_HOST_BIT_ENABLE (1 << 7) | 59 | #define CODA7_USE_HOST_BIT_ENABLE (1 << 7) |
52 | #define CODA7_USE_ME_ENABLE (1 << 4) | 60 | #define CODA7_USE_ME_ENABLE (1 << 4) |
53 | #define CODA7_USE_HOST_ME_ENABLE (1 << 11) | 61 | #define CODA7_USE_OVL_ENABLE (1 << 3) |
62 | #define CODA7_USE_DBK_ENABLE (1 << 2) | ||
63 | #define CODA7_USE_IP_ENABLE (1 << 1) | ||
64 | #define CODA7_USE_BIT_ENABLE (1 << 0) | ||
65 | |||
54 | #define CODA_REG_BIT_BUSY 0x160 | 66 | #define CODA_REG_BIT_BUSY 0x160 |
55 | #define CODA_REG_BIT_BUSY_FLAG 1 | 67 | #define CODA_REG_BIT_BUSY_FLAG 1 |
56 | #define CODA_REG_BIT_RUN_COMMAND 0x164 | 68 | #define CODA_REG_BIT_RUN_COMMAND 0x164 |
@@ -84,6 +96,15 @@ | |||
84 | #define CODA_MODE_INVALID 0xffff | 96 | #define CODA_MODE_INVALID 0xffff |
85 | #define CODA_REG_BIT_INT_ENABLE 0x170 | 97 | #define CODA_REG_BIT_INT_ENABLE 0x170 |
86 | #define CODA_INT_INTERRUPT_ENABLE (1 << 3) | 98 | #define CODA_INT_INTERRUPT_ENABLE (1 << 3) |
99 | #define CODA_REG_BIT_INT_REASON 0x174 | ||
100 | #define CODA7_REG_BIT_RUN_AUX_STD 0x178 | ||
101 | #define CODA_MP4_AUX_MPEG4 0 | ||
102 | #define CODA_MP4_AUX_DIVX3 1 | ||
103 | #define CODA_VPX_AUX_THO 0 | ||
104 | #define CODA_VPX_AUX_VP6 1 | ||
105 | #define CODA_VPX_AUX_VP8 2 | ||
106 | #define CODA_H264_AUX_AVC 0 | ||
107 | #define CODA_H264_AUX_MVC 1 | ||
87 | 108 | ||
88 | /* | 109 | /* |
89 | * Commands' mailbox: | 110 | * Commands' mailbox: |
@@ -92,15 +113,89 @@ | |||
92 | * issued. | 113 | * issued. |
93 | */ | 114 | */ |
94 | 115 | ||
116 | /* Decoder Sequence Initialization */ | ||
117 | #define CODA_CMD_DEC_SEQ_BB_START 0x180 | ||
118 | #define CODA_CMD_DEC_SEQ_BB_SIZE 0x184 | ||
119 | #define CODA_CMD_DEC_SEQ_OPTION 0x188 | ||
120 | #define CODA_REORDER_ENABLE (1 << 1) | ||
121 | #define CODADX6_QP_REPORT (1 << 0) | ||
122 | #define CODA7_MP4_DEBLK_ENABLE (1 << 0) | ||
123 | #define CODA_CMD_DEC_SEQ_SRC_SIZE 0x18c | ||
124 | #define CODA_CMD_DEC_SEQ_START_BYTE 0x190 | ||
125 | #define CODA_CMD_DEC_SEQ_PS_BB_START 0x194 | ||
126 | #define CODA_CMD_DEC_SEQ_PS_BB_SIZE 0x198 | ||
127 | #define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS 0x19c | ||
128 | #define CODA_CMD_DEC_SEQ_X264_MV_EN 0x19c | ||
129 | #define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0 | ||
130 | |||
131 | #define CODA7_RET_DEC_SEQ_ASPECT 0x1b0 | ||
132 | #define CODA_RET_DEC_SEQ_SUCCESS 0x1c0 | ||
133 | #define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */ | ||
134 | #define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4 | ||
135 | #define CODA_RET_DEC_SEQ_SRC_F_RATE 0x1c8 | ||
136 | #define CODA9_RET_DEC_SEQ_ASPECT 0x1c8 | ||
137 | #define CODA_RET_DEC_SEQ_FRAME_NEED 0x1cc | ||
138 | #define CODA_RET_DEC_SEQ_FRAME_DELAY 0x1d0 | ||
139 | #define CODA_RET_DEC_SEQ_INFO 0x1d4 | ||
140 | #define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT 0x1d8 | ||
141 | #define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM 0x1dc | ||
142 | #define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM 0x1e0 | ||
143 | #define CODA_RET_DEC_SEQ_ERR_REASON 0x1e0 | ||
144 | #define CODA_RET_DEC_SEQ_FRATE_NR 0x1e4 | ||
145 | #define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8 | ||
146 | #define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4 | ||
147 | #define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8 | ||
148 | |||
149 | /* Decoder Picture Run */ | ||
150 | #define CODA_CMD_DEC_PIC_ROT_MODE 0x180 | ||
151 | #define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184 | ||
152 | #define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188 | ||
153 | #define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c | ||
154 | #define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190 | ||
155 | |||
156 | #define CODA_CMD_DEC_PIC_OPTION 0x194 | ||
157 | #define CODA_PRE_SCAN_EN (1 << 0) | ||
158 | #define CODA_PRE_SCAN_MODE_DECODE (0 << 1) | ||
159 | #define CODA_PRE_SCAN_MODE_RETURN (1 << 1) | ||
160 | #define CODA_IFRAME_SEARCH_EN (1 << 2) | ||
161 | #define CODA_SKIP_FRAME_MODE (0x3 << 3) | ||
162 | #define CODA_CMD_DEC_PIC_SKIP_NUM 0x198 | ||
163 | #define CODA_CMD_DEC_PIC_CHUNK_SIZE 0x19c | ||
164 | #define CODA_CMD_DEC_PIC_BB_START 0x1a0 | ||
165 | #define CODA_CMD_DEC_PIC_START_BYTE 0x1a4 | ||
166 | #define CODA_RET_DEC_PIC_SIZE 0x1bc | ||
167 | #define CODA_RET_DEC_PIC_FRAME_NUM 0x1c0 | ||
168 | #define CODA_RET_DEC_PIC_FRAME_IDX 0x1c4 | ||
169 | #define CODA_RET_DEC_PIC_ERR_MB 0x1c8 | ||
170 | #define CODA_RET_DEC_PIC_TYPE 0x1cc | ||
171 | #define CODA_PIC_TYPE_MASK 0x7 | ||
172 | #define CODA_PIC_TYPE_MASK_VC1 0x3f | ||
173 | #define CODA9_PIC_TYPE_FIRST_MASK (0x7 << 3) | ||
174 | #define CODA9_PIC_TYPE_IDR_MASK (0x3 << 6) | ||
175 | #define CODA7_PIC_TYPE_H264_NPF_MASK (0x3 << 16) | ||
176 | #define CODA7_PIC_TYPE_INTERLACED (1 << 18) | ||
177 | #define CODA_RET_DEC_PIC_POST 0x1d0 | ||
178 | #define CODA_RET_DEC_PIC_MVC_REPORT 0x1d0 | ||
179 | #define CODA_RET_DEC_PIC_OPTION 0x1d4 | ||
180 | #define CODA_RET_DEC_PIC_SUCCESS 0x1d8 | ||
181 | #define CODA_RET_DEC_PIC_CUR_IDX 0x1dc | ||
182 | #define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT 0x1e0 | ||
183 | #define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4 | ||
184 | #define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec | ||
185 | |||
95 | /* Encoder Sequence Initialization */ | 186 | /* Encoder Sequence Initialization */ |
96 | #define CODA_CMD_ENC_SEQ_BB_START 0x180 | 187 | #define CODA_CMD_ENC_SEQ_BB_START 0x180 |
97 | #define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 | 188 | #define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 |
98 | #define CODA_CMD_ENC_SEQ_OPTION 0x188 | 189 | #define CODA_CMD_ENC_SEQ_OPTION 0x188 |
190 | #define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9 | ||
99 | #define CODA7_OPTION_GAMMA_OFFSET 8 | 191 | #define CODA7_OPTION_GAMMA_OFFSET 8 |
192 | #define CODA7_OPTION_RCQPMAX_OFFSET 7 | ||
100 | #define CODADX6_OPTION_GAMMA_OFFSET 7 | 193 | #define CODADX6_OPTION_GAMMA_OFFSET 7 |
194 | #define CODA7_OPTION_RCQPMIN_OFFSET 6 | ||
101 | #define CODA_OPTION_LIMITQP_OFFSET 6 | 195 | #define CODA_OPTION_LIMITQP_OFFSET 6 |
102 | #define CODA_OPTION_RCINTRAQP_OFFSET 5 | 196 | #define CODA_OPTION_RCINTRAQP_OFFSET 5 |
103 | #define CODA_OPTION_FMO_OFFSET 4 | 197 | #define CODA_OPTION_FMO_OFFSET 4 |
198 | #define CODA_OPTION_AVC_AUD_OFFSET 2 | ||
104 | #define CODA_OPTION_SLICEREPORT_OFFSET 1 | 199 | #define CODA_OPTION_SLICEREPORT_OFFSET 1 |
105 | #define CODA_CMD_ENC_SEQ_COD_STD 0x18c | 200 | #define CODA_CMD_ENC_SEQ_COD_STD 0x18c |
106 | #define CODA_STD_MPEG4 0 | 201 | #define CODA_STD_MPEG4 0 |
@@ -169,8 +264,10 @@ | |||
169 | #define CODA_FMOPARAM_TYPE_MASK 1 | 264 | #define CODA_FMOPARAM_TYPE_MASK 1 |
170 | #define CODA_FMOPARAM_SLICENUM_OFFSET 0 | 265 | #define CODA_FMOPARAM_SLICENUM_OFFSET 0 |
171 | #define CODA_FMOPARAM_SLICENUM_MASK 0x0f | 266 | #define CODA_FMOPARAM_SLICENUM_MASK 0x0f |
267 | #define CODADX6_CMD_ENC_SEQ_INTRA_QP 0x1bc | ||
172 | #define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 | 268 | #define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 |
173 | #define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc | 269 | #define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc |
270 | #define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4 | ||
174 | #define CODA_CMD_ENC_SEQ_RC_QP_MAX 0x1c8 | 271 | #define CODA_CMD_ENC_SEQ_RC_QP_MAX 0x1c8 |
175 | #define CODA_QPMAX_OFFSET 0 | 272 | #define CODA_QPMAX_OFFSET 0 |
176 | #define CODA_QPMAX_MASK 0x3f | 273 | #define CODA_QPMAX_MASK 0x3f |
@@ -197,18 +294,24 @@ | |||
197 | #define CODA_CMD_ENC_PIC_OPTION 0x194 | 294 | #define CODA_CMD_ENC_PIC_OPTION 0x194 |
198 | #define CODA_CMD_ENC_PIC_BB_START 0x198 | 295 | #define CODA_CMD_ENC_PIC_BB_START 0x198 |
199 | #define CODA_CMD_ENC_PIC_BB_SIZE 0x19c | 296 | #define CODA_CMD_ENC_PIC_BB_SIZE 0x19c |
297 | #define CODA_RET_ENC_FRAME_NUM 0x1c0 | ||
200 | #define CODA_RET_ENC_PIC_TYPE 0x1c4 | 298 | #define CODA_RET_ENC_PIC_TYPE 0x1c4 |
299 | #define CODA_RET_ENC_PIC_FRAME_IDX 0x1c8 | ||
201 | #define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc | 300 | #define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc |
202 | #define CODA_RET_ENC_PIC_FLAG 0x1d0 | 301 | #define CODA_RET_ENC_PIC_FLAG 0x1d0 |
302 | #define CODA_RET_ENC_PIC_SUCCESS 0x1d8 | ||
203 | 303 | ||
204 | /* Set Frame Buffer */ | 304 | /* Set Frame Buffer */ |
205 | #define CODA_CMD_SET_FRAME_BUF_NUM 0x180 | 305 | #define CODA_CMD_SET_FRAME_BUF_NUM 0x180 |
206 | #define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 | 306 | #define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 |
307 | #define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188 | ||
308 | #define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c | ||
207 | #define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 | 309 | #define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 |
208 | #define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 | 310 | #define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 |
209 | #define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 | 311 | #define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 |
210 | #define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c | 312 | #define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c |
211 | #define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 | 313 | #define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 |
314 | #define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4 | ||
212 | #define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 | 315 | #define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 |
213 | 316 | ||
214 | /* Encoder Header */ | 317 | /* Encoder Header */ |
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index e180ff7282d9..04609cc6eba7 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c | |||
@@ -1743,11 +1743,10 @@ static int vpbe_display_probe(struct platform_device *pdev) | |||
1743 | 1743 | ||
1744 | printk(KERN_DEBUG "vpbe_display_probe\n"); | 1744 | printk(KERN_DEBUG "vpbe_display_probe\n"); |
1745 | /* Allocate memory for vpbe_display */ | 1745 | /* Allocate memory for vpbe_display */ |
1746 | disp_dev = kzalloc(sizeof(struct vpbe_display), GFP_KERNEL); | 1746 | disp_dev = devm_kzalloc(&pdev->dev, sizeof(struct vpbe_display), |
1747 | if (!disp_dev) { | 1747 | GFP_KERNEL); |
1748 | printk(KERN_ERR "ran out of memory\n"); | 1748 | if (!disp_dev) |
1749 | return -ENOMEM; | 1749 | return -ENOMEM; |
1750 | } | ||
1751 | 1750 | ||
1752 | spin_lock_init(&disp_dev->dma_queue_lock); | 1751 | spin_lock_init(&disp_dev->dma_queue_lock); |
1753 | /* | 1752 | /* |
@@ -1786,26 +1785,24 @@ static int vpbe_display_probe(struct platform_device *pdev) | |||
1786 | } | 1785 | } |
1787 | 1786 | ||
1788 | irq = res->start; | 1787 | irq = res->start; |
1789 | if (request_irq(irq, venc_isr, IRQF_DISABLED, VPBE_DISPLAY_DRIVER, | 1788 | err = devm_request_irq(&pdev->dev, irq, venc_isr, IRQF_DISABLED, |
1790 | disp_dev)) { | 1789 | VPBE_DISPLAY_DRIVER, disp_dev); |
1790 | if (err) { | ||
1791 | v4l2_err(&disp_dev->vpbe_dev->v4l2_dev, | 1791 | v4l2_err(&disp_dev->vpbe_dev->v4l2_dev, |
1792 | "Unable to request interrupt\n"); | 1792 | "Unable to request interrupt\n"); |
1793 | err = -ENODEV; | ||
1794 | goto probe_out; | 1793 | goto probe_out; |
1795 | } | 1794 | } |
1796 | 1795 | ||
1797 | for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { | 1796 | for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { |
1798 | if (register_device(disp_dev->dev[i], disp_dev, pdev)) { | 1797 | if (register_device(disp_dev->dev[i], disp_dev, pdev)) { |
1799 | err = -ENODEV; | 1798 | err = -ENODEV; |
1800 | goto probe_out_irq; | 1799 | goto probe_out; |
1801 | } | 1800 | } |
1802 | } | 1801 | } |
1803 | 1802 | ||
1804 | printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n"); | 1803 | printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n"); |
1805 | return 0; | 1804 | return 0; |
1806 | 1805 | ||
1807 | probe_out_irq: | ||
1808 | free_irq(res->start, disp_dev); | ||
1809 | probe_out: | 1806 | probe_out: |
1810 | for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) { | 1807 | for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) { |
1811 | /* Get the pointer to the layer object */ | 1808 | /* Get the pointer to the layer object */ |
@@ -1817,7 +1814,6 @@ probe_out: | |||
1817 | kfree(disp_dev->dev[k]); | 1814 | kfree(disp_dev->dev[k]); |
1818 | } | 1815 | } |
1819 | } | 1816 | } |
1820 | kfree(disp_dev); | ||
1821 | return err; | 1817 | return err; |
1822 | } | 1818 | } |
1823 | 1819 | ||
@@ -1830,15 +1826,10 @@ static int vpbe_display_remove(struct platform_device *pdev) | |||
1830 | struct vpbe_layer *vpbe_display_layer; | 1826 | struct vpbe_layer *vpbe_display_layer; |
1831 | struct vpbe_display *disp_dev = platform_get_drvdata(pdev); | 1827 | struct vpbe_display *disp_dev = platform_get_drvdata(pdev); |
1832 | struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev; | 1828 | struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev; |
1833 | struct resource *res; | ||
1834 | int i; | 1829 | int i; |
1835 | 1830 | ||
1836 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n"); | 1831 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n"); |
1837 | 1832 | ||
1838 | /* unregister irq */ | ||
1839 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
1840 | free_irq(res->start, disp_dev); | ||
1841 | |||
1842 | /* deinitialize the vpbe display controller */ | 1833 | /* deinitialize the vpbe display controller */ |
1843 | if (NULL != vpbe_dev->ops.deinitialize) | 1834 | if (NULL != vpbe_dev->ops.deinitialize) |
1844 | vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev); | 1835 | vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev); |
diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c index 6ed82e8b297b..d053c2669c1f 100644 --- a/drivers/media/platform/davinci/vpbe_osd.c +++ b/drivers/media/platform/davinci/vpbe_osd.c | |||
@@ -1547,61 +1547,36 @@ static int osd_probe(struct platform_device *pdev) | |||
1547 | const struct platform_device_id *pdev_id; | 1547 | const struct platform_device_id *pdev_id; |
1548 | struct osd_state *osd; | 1548 | struct osd_state *osd; |
1549 | struct resource *res; | 1549 | struct resource *res; |
1550 | int ret = 0; | ||
1551 | 1550 | ||
1552 | osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL); | 1551 | pdev_id = platform_get_device_id(pdev); |
1552 | if (!pdev_id) | ||
1553 | return -EINVAL; | ||
1554 | |||
1555 | osd = devm_kzalloc(&pdev->dev, sizeof(struct osd_state), GFP_KERNEL); | ||
1553 | if (osd == NULL) | 1556 | if (osd == NULL) |
1554 | return -ENOMEM; | 1557 | return -ENOMEM; |
1555 | 1558 | ||
1556 | pdev_id = platform_get_device_id(pdev); | ||
1557 | if (!pdev_id) { | ||
1558 | ret = -EINVAL; | ||
1559 | goto free_mem; | ||
1560 | } | ||
1561 | 1559 | ||
1562 | osd->dev = &pdev->dev; | 1560 | osd->dev = &pdev->dev; |
1563 | osd->vpbe_type = pdev_id->driver_data; | 1561 | osd->vpbe_type = pdev_id->driver_data; |
1564 | 1562 | ||
1565 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1563 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1566 | if (!res) { | 1564 | osd->osd_base = devm_ioremap_resource(&pdev->dev, res); |
1567 | dev_err(osd->dev, "Unable to get OSD register address map\n"); | 1565 | if (IS_ERR(osd->osd_base)) |
1568 | ret = -ENODEV; | 1566 | return PTR_ERR(osd->osd_base); |
1569 | goto free_mem; | 1567 | |
1570 | } | ||
1571 | osd->osd_base_phys = res->start; | 1568 | osd->osd_base_phys = res->start; |
1572 | osd->osd_size = resource_size(res); | 1569 | osd->osd_size = resource_size(res); |
1573 | if (!request_mem_region(osd->osd_base_phys, osd->osd_size, | ||
1574 | MODULE_NAME)) { | ||
1575 | dev_err(osd->dev, "Unable to reserve OSD MMIO region\n"); | ||
1576 | ret = -ENODEV; | ||
1577 | goto free_mem; | ||
1578 | } | ||
1579 | osd->osd_base = ioremap_nocache(res->start, osd->osd_size); | ||
1580 | if (!osd->osd_base) { | ||
1581 | dev_err(osd->dev, "Unable to map the OSD region\n"); | ||
1582 | ret = -ENODEV; | ||
1583 | goto release_mem_region; | ||
1584 | } | ||
1585 | spin_lock_init(&osd->lock); | 1570 | spin_lock_init(&osd->lock); |
1586 | osd->ops = osd_ops; | 1571 | osd->ops = osd_ops; |
1587 | platform_set_drvdata(pdev, osd); | 1572 | platform_set_drvdata(pdev, osd); |
1588 | dev_notice(osd->dev, "OSD sub device probe success\n"); | 1573 | dev_notice(osd->dev, "OSD sub device probe success\n"); |
1589 | return ret; | ||
1590 | 1574 | ||
1591 | release_mem_region: | 1575 | return 0; |
1592 | release_mem_region(osd->osd_base_phys, osd->osd_size); | ||
1593 | free_mem: | ||
1594 | kfree(osd); | ||
1595 | return ret; | ||
1596 | } | 1576 | } |
1597 | 1577 | ||
1598 | static int osd_remove(struct platform_device *pdev) | 1578 | static int osd_remove(struct platform_device *pdev) |
1599 | { | 1579 | { |
1600 | struct osd_state *osd = platform_get_drvdata(pdev); | ||
1601 | |||
1602 | iounmap((void *)osd->osd_base); | ||
1603 | release_mem_region(osd->osd_base_phys, osd->osd_size); | ||
1604 | kfree(osd); | ||
1605 | return 0; | 1580 | return 0; |
1606 | } | 1581 | } |
1607 | 1582 | ||
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index 87eef9be08ed..14a023a75d2d 100644 --- a/drivers/media/platform/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c | |||
@@ -639,105 +639,46 @@ static int venc_probe(struct platform_device *pdev) | |||
639 | const struct platform_device_id *pdev_id; | 639 | const struct platform_device_id *pdev_id; |
640 | struct venc_state *venc; | 640 | struct venc_state *venc; |
641 | struct resource *res; | 641 | struct resource *res; |
642 | int ret; | ||
643 | 642 | ||
644 | venc = kzalloc(sizeof(struct venc_state), GFP_KERNEL); | 643 | if (!pdev->dev.platform_data) { |
644 | dev_err(&pdev->dev, "No platform data for VENC sub device"); | ||
645 | return -EINVAL; | ||
646 | } | ||
647 | |||
648 | pdev_id = platform_get_device_id(pdev); | ||
649 | if (!pdev_id) | ||
650 | return -EINVAL; | ||
651 | |||
652 | venc = devm_kzalloc(&pdev->dev, sizeof(struct venc_state), GFP_KERNEL); | ||
645 | if (venc == NULL) | 653 | if (venc == NULL) |
646 | return -ENOMEM; | 654 | return -ENOMEM; |
647 | 655 | ||
648 | pdev_id = platform_get_device_id(pdev); | ||
649 | if (!pdev_id) { | ||
650 | ret = -EINVAL; | ||
651 | goto free_mem; | ||
652 | } | ||
653 | venc->venc_type = pdev_id->driver_data; | 656 | venc->venc_type = pdev_id->driver_data; |
654 | venc->pdev = &pdev->dev; | 657 | venc->pdev = &pdev->dev; |
655 | venc->pdata = pdev->dev.platform_data; | 658 | venc->pdata = pdev->dev.platform_data; |
656 | if (NULL == venc->pdata) { | 659 | |
657 | dev_err(venc->pdev, "Unable to get platform data for" | ||
658 | " VENC sub device"); | ||
659 | ret = -ENOENT; | ||
660 | goto free_mem; | ||
661 | } | ||
662 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 660 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
663 | if (!res) { | ||
664 | dev_err(venc->pdev, | ||
665 | "Unable to get VENC register address map\n"); | ||
666 | ret = -ENODEV; | ||
667 | goto free_mem; | ||
668 | } | ||
669 | 661 | ||
670 | if (!request_mem_region(res->start, resource_size(res), "venc")) { | 662 | venc->venc_base = devm_ioremap_resource(&pdev->dev, res); |
671 | dev_err(venc->pdev, "Unable to reserve VENC MMIO region\n"); | 663 | if (IS_ERR(venc->venc_base)) |
672 | ret = -ENODEV; | 664 | return PTR_ERR(venc->venc_base); |
673 | goto free_mem; | ||
674 | } | ||
675 | |||
676 | venc->venc_base = ioremap_nocache(res->start, resource_size(res)); | ||
677 | if (!venc->venc_base) { | ||
678 | dev_err(venc->pdev, "Unable to map VENC IO space\n"); | ||
679 | ret = -ENODEV; | ||
680 | goto release_venc_mem_region; | ||
681 | } | ||
682 | 665 | ||
683 | if (venc->venc_type != VPBE_VERSION_1) { | 666 | if (venc->venc_type != VPBE_VERSION_1) { |
684 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 667 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
685 | if (!res) { | 668 | |
686 | dev_err(venc->pdev, | 669 | venc->vdaccfg_reg = devm_ioremap_resource(&pdev->dev, res); |
687 | "Unable to get VDAC_CONFIG address map\n"); | 670 | if (IS_ERR(venc->vdaccfg_reg)) |
688 | ret = -ENODEV; | 671 | return PTR_ERR(venc->vdaccfg_reg); |
689 | goto unmap_venc_io; | ||
690 | } | ||
691 | |||
692 | if (!request_mem_region(res->start, | ||
693 | resource_size(res), "venc")) { | ||
694 | dev_err(venc->pdev, | ||
695 | "Unable to reserve VDAC_CONFIG MMIO region\n"); | ||
696 | ret = -ENODEV; | ||
697 | goto unmap_venc_io; | ||
698 | } | ||
699 | |||
700 | venc->vdaccfg_reg = ioremap_nocache(res->start, | ||
701 | resource_size(res)); | ||
702 | if (!venc->vdaccfg_reg) { | ||
703 | dev_err(venc->pdev, | ||
704 | "Unable to map VDAC_CONFIG IO space\n"); | ||
705 | ret = -ENODEV; | ||
706 | goto release_vdaccfg_mem_region; | ||
707 | } | ||
708 | } | 672 | } |
709 | spin_lock_init(&venc->lock); | 673 | spin_lock_init(&venc->lock); |
710 | platform_set_drvdata(pdev, venc); | 674 | platform_set_drvdata(pdev, venc); |
711 | dev_notice(venc->pdev, "VENC sub device probe success\n"); | 675 | dev_notice(venc->pdev, "VENC sub device probe success\n"); |
712 | return 0; | ||
713 | 676 | ||
714 | release_vdaccfg_mem_region: | 677 | return 0; |
715 | release_mem_region(res->start, resource_size(res)); | ||
716 | unmap_venc_io: | ||
717 | iounmap(venc->venc_base); | ||
718 | release_venc_mem_region: | ||
719 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
720 | release_mem_region(res->start, resource_size(res)); | ||
721 | free_mem: | ||
722 | kfree(venc); | ||
723 | return ret; | ||
724 | } | 678 | } |
725 | 679 | ||
726 | static int venc_remove(struct platform_device *pdev) | 680 | static int venc_remove(struct platform_device *pdev) |
727 | { | 681 | { |
728 | struct venc_state *venc = platform_get_drvdata(pdev); | ||
729 | struct resource *res; | ||
730 | |||
731 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
732 | iounmap((void *)venc->venc_base); | ||
733 | release_mem_region(res->start, resource_size(res)); | ||
734 | if (venc->venc_type != VPBE_VERSION_1) { | ||
735 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
736 | iounmap((void *)venc->vdaccfg_reg); | ||
737 | release_mem_region(res->start, resource_size(res)); | ||
738 | } | ||
739 | kfree(venc); | ||
740 | |||
741 | return 0; | 682 | return 0; |
742 | } | 683 | } |
743 | 684 | ||
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 5514175bbd07..1089834a4efe 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c | |||
@@ -1799,19 +1799,15 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
1799 | 1799 | ||
1800 | /* Configure video port timings */ | 1800 | /* Configure video port timings */ |
1801 | 1801 | ||
1802 | std_info->eav2sav = bt->hbackporch + bt->hfrontporch + | 1802 | std_info->eav2sav = V4L2_DV_BT_BLANKING_WIDTH(bt) - 8; |
1803 | bt->hsync - 8; | ||
1804 | std_info->sav2eav = bt->width; | 1803 | std_info->sav2eav = bt->width; |
1805 | 1804 | ||
1806 | std_info->l1 = 1; | 1805 | std_info->l1 = 1; |
1807 | std_info->l3 = bt->vsync + bt->vbackporch + 1; | 1806 | std_info->l3 = bt->vsync + bt->vbackporch + 1; |
1808 | 1807 | ||
1808 | std_info->vsize = V4L2_DV_BT_FRAME_HEIGHT(bt); | ||
1809 | if (bt->interlaced) { | 1809 | if (bt->interlaced) { |
1810 | if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { | 1810 | if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { |
1811 | std_info->vsize = bt->height * 2 + | ||
1812 | bt->vfrontporch + bt->vsync + bt->vbackporch + | ||
1813 | bt->il_vfrontporch + bt->il_vsync + | ||
1814 | bt->il_vbackporch; | ||
1815 | std_info->l5 = std_info->vsize/2 - | 1811 | std_info->l5 = std_info->vsize/2 - |
1816 | (bt->vfrontporch - 1); | 1812 | (bt->vfrontporch - 1); |
1817 | std_info->l7 = std_info->vsize/2 + 1; | 1813 | std_info->l7 = std_info->vsize/2 + 1; |
@@ -1825,8 +1821,6 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
1825 | return -EINVAL; | 1821 | return -EINVAL; |
1826 | } | 1822 | } |
1827 | } else { | 1823 | } else { |
1828 | std_info->vsize = bt->height + bt->vfrontporch + | ||
1829 | bt->vsync + bt->vbackporch; | ||
1830 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); | 1824 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); |
1831 | } | 1825 | } |
1832 | strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME); | 1826 | strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME); |
@@ -1979,6 +1973,76 @@ vpif_init_free_channel_objects: | |||
1979 | return err; | 1973 | return err; |
1980 | } | 1974 | } |
1981 | 1975 | ||
1976 | static int vpif_async_bound(struct v4l2_async_notifier *notifier, | ||
1977 | struct v4l2_subdev *subdev, | ||
1978 | struct v4l2_async_subdev *asd) | ||
1979 | { | ||
1980 | int i; | ||
1981 | |||
1982 | for (i = 0; i < vpif_obj.config->subdev_count; i++) | ||
1983 | if (!strcmp(vpif_obj.config->subdev_info[i].name, | ||
1984 | subdev->name)) { | ||
1985 | vpif_obj.sd[i] = subdev; | ||
1986 | return 0; | ||
1987 | } | ||
1988 | |||
1989 | return -EINVAL; | ||
1990 | } | ||
1991 | |||
1992 | static int vpif_probe_complete(void) | ||
1993 | { | ||
1994 | struct common_obj *common; | ||
1995 | struct channel_obj *ch; | ||
1996 | int i, j, err, k; | ||
1997 | |||
1998 | for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { | ||
1999 | ch = vpif_obj.dev[j]; | ||
2000 | ch->channel_id = j; | ||
2001 | common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
2002 | spin_lock_init(&common->irqlock); | ||
2003 | mutex_init(&common->lock); | ||
2004 | ch->video_dev->lock = &common->lock; | ||
2005 | /* Initialize prio member of channel object */ | ||
2006 | v4l2_prio_init(&ch->prio); | ||
2007 | video_set_drvdata(ch->video_dev, ch); | ||
2008 | |||
2009 | /* select input 0 */ | ||
2010 | err = vpif_set_input(vpif_obj.config, ch, 0); | ||
2011 | if (err) | ||
2012 | goto probe_out; | ||
2013 | |||
2014 | err = video_register_device(ch->video_dev, | ||
2015 | VFL_TYPE_GRABBER, (j ? 1 : 0)); | ||
2016 | if (err) | ||
2017 | goto probe_out; | ||
2018 | } | ||
2019 | |||
2020 | v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); | ||
2021 | return 0; | ||
2022 | |||
2023 | probe_out: | ||
2024 | for (k = 0; k < j; k++) { | ||
2025 | /* Get the pointer to the channel object */ | ||
2026 | ch = vpif_obj.dev[k]; | ||
2027 | /* Unregister video device */ | ||
2028 | video_unregister_device(ch->video_dev); | ||
2029 | } | ||
2030 | kfree(vpif_obj.sd); | ||
2031 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { | ||
2032 | ch = vpif_obj.dev[i]; | ||
2033 | /* Note: does nothing if ch->video_dev == NULL */ | ||
2034 | video_device_release(ch->video_dev); | ||
2035 | } | ||
2036 | v4l2_device_unregister(&vpif_obj.v4l2_dev); | ||
2037 | |||
2038 | return err; | ||
2039 | } | ||
2040 | |||
2041 | static int vpif_async_complete(struct v4l2_async_notifier *notifier) | ||
2042 | { | ||
2043 | return vpif_probe_complete(); | ||
2044 | } | ||
2045 | |||
1982 | /** | 2046 | /** |
1983 | * vpif_probe : This function probes the vpif capture driver | 2047 | * vpif_probe : This function probes the vpif capture driver |
1984 | * @pdev: platform device pointer | 2048 | * @pdev: platform device pointer |
@@ -1989,12 +2053,10 @@ vpif_init_free_channel_objects: | |||
1989 | static __init int vpif_probe(struct platform_device *pdev) | 2053 | static __init int vpif_probe(struct platform_device *pdev) |
1990 | { | 2054 | { |
1991 | struct vpif_subdev_info *subdevdata; | 2055 | struct vpif_subdev_info *subdevdata; |
1992 | struct vpif_capture_config *config; | 2056 | int i, j, err; |
1993 | int i, j, k, err; | ||
1994 | int res_idx = 0; | 2057 | int res_idx = 0; |
1995 | struct i2c_adapter *i2c_adap; | 2058 | struct i2c_adapter *i2c_adap; |
1996 | struct channel_obj *ch; | 2059 | struct channel_obj *ch; |
1997 | struct common_obj *common; | ||
1998 | struct video_device *vfd; | 2060 | struct video_device *vfd; |
1999 | struct resource *res; | 2061 | struct resource *res; |
2000 | int subdev_count; | 2062 | int subdev_count; |
@@ -2068,10 +2130,9 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2068 | } | 2130 | } |
2069 | } | 2131 | } |
2070 | 2132 | ||
2071 | i2c_adap = i2c_get_adapter(1); | 2133 | vpif_obj.config = pdev->dev.platform_data; |
2072 | config = pdev->dev.platform_data; | ||
2073 | 2134 | ||
2074 | subdev_count = config->subdev_count; | 2135 | subdev_count = vpif_obj.config->subdev_count; |
2075 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, | 2136 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, |
2076 | GFP_KERNEL); | 2137 | GFP_KERNEL); |
2077 | if (vpif_obj.sd == NULL) { | 2138 | if (vpif_obj.sd == NULL) { |
@@ -2080,54 +2141,43 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2080 | goto vpif_sd_error; | 2141 | goto vpif_sd_error; |
2081 | } | 2142 | } |
2082 | 2143 | ||
2083 | for (i = 0; i < subdev_count; i++) { | 2144 | if (!vpif_obj.config->asd_sizes) { |
2084 | subdevdata = &config->subdev_info[i]; | 2145 | i2c_adap = i2c_get_adapter(1); |
2085 | vpif_obj.sd[i] = | 2146 | for (i = 0; i < subdev_count; i++) { |
2086 | v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, | 2147 | subdevdata = &vpif_obj.config->subdev_info[i]; |
2087 | i2c_adap, | 2148 | vpif_obj.sd[i] = |
2088 | &subdevdata->board_info, | 2149 | v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, |
2089 | NULL); | 2150 | i2c_adap, |
2090 | 2151 | &subdevdata-> | |
2091 | if (!vpif_obj.sd[i]) { | 2152 | board_info, |
2092 | vpif_err("Error registering v4l2 subdevice\n"); | 2153 | NULL); |
2093 | err = -ENODEV; | 2154 | |
2155 | if (!vpif_obj.sd[i]) { | ||
2156 | vpif_err("Error registering v4l2 subdevice\n"); | ||
2157 | err = -ENOMEM; | ||
2158 | goto probe_subdev_out; | ||
2159 | } | ||
2160 | v4l2_info(&vpif_obj.v4l2_dev, | ||
2161 | "registered sub device %s\n", | ||
2162 | subdevdata->name); | ||
2163 | } | ||
2164 | vpif_probe_complete(); | ||
2165 | } else { | ||
2166 | vpif_obj.notifier.subdevs = vpif_obj.config->asd; | ||
2167 | vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; | ||
2168 | vpif_obj.notifier.bound = vpif_async_bound; | ||
2169 | vpif_obj.notifier.complete = vpif_async_complete; | ||
2170 | err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, | ||
2171 | &vpif_obj.notifier); | ||
2172 | if (err) { | ||
2173 | vpif_err("Error registering async notifier\n"); | ||
2174 | err = -EINVAL; | ||
2094 | goto probe_subdev_out; | 2175 | goto probe_subdev_out; |
2095 | } | 2176 | } |
2096 | v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", | ||
2097 | subdevdata->name); | ||
2098 | } | 2177 | } |
2099 | 2178 | ||
2100 | for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { | ||
2101 | ch = vpif_obj.dev[j]; | ||
2102 | ch->channel_id = j; | ||
2103 | common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
2104 | spin_lock_init(&common->irqlock); | ||
2105 | mutex_init(&common->lock); | ||
2106 | ch->video_dev->lock = &common->lock; | ||
2107 | /* Initialize prio member of channel object */ | ||
2108 | v4l2_prio_init(&ch->prio); | ||
2109 | video_set_drvdata(ch->video_dev, ch); | ||
2110 | |||
2111 | /* select input 0 */ | ||
2112 | err = vpif_set_input(config, ch, 0); | ||
2113 | if (err) | ||
2114 | goto probe_out; | ||
2115 | |||
2116 | err = video_register_device(ch->video_dev, | ||
2117 | VFL_TYPE_GRABBER, (j ? 1 : 0)); | ||
2118 | if (err) | ||
2119 | goto probe_out; | ||
2120 | } | ||
2121 | v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); | ||
2122 | return 0; | 2179 | return 0; |
2123 | 2180 | ||
2124 | probe_out: | ||
2125 | for (k = 0; k < j; k++) { | ||
2126 | /* Get the pointer to the channel object */ | ||
2127 | ch = vpif_obj.dev[k]; | ||
2128 | /* Unregister video device */ | ||
2129 | video_unregister_device(ch->video_dev); | ||
2130 | } | ||
2131 | probe_subdev_out: | 2181 | probe_subdev_out: |
2132 | /* free sub devices memory */ | 2182 | /* free sub devices memory */ |
2133 | kfree(vpif_obj.sd); | 2183 | kfree(vpif_obj.sd); |
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 0ebb31260369..5a29d9a0cae1 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h | |||
@@ -142,6 +142,8 @@ struct vpif_device { | |||
142 | struct v4l2_device v4l2_dev; | 142 | struct v4l2_device v4l2_dev; |
143 | struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; | 143 | struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; |
144 | struct v4l2_subdev **sd; | 144 | struct v4l2_subdev **sd; |
145 | struct v4l2_async_notifier notifier; | ||
146 | struct vpif_capture_config *config; | ||
145 | }; | 147 | }; |
146 | 148 | ||
147 | struct vpif_config_params { | 149 | struct vpif_config_params { |
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index e6e573650250..c31bcf129a5d 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c | |||
@@ -1436,19 +1436,15 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
1436 | 1436 | ||
1437 | /* Configure video port timings */ | 1437 | /* Configure video port timings */ |
1438 | 1438 | ||
1439 | std_info->eav2sav = bt->hbackporch + bt->hfrontporch + | 1439 | std_info->eav2sav = V4L2_DV_BT_BLANKING_WIDTH(bt) - 8; |
1440 | bt->hsync - 8; | ||
1441 | std_info->sav2eav = bt->width; | 1440 | std_info->sav2eav = bt->width; |
1442 | 1441 | ||
1443 | std_info->l1 = 1; | 1442 | std_info->l1 = 1; |
1444 | std_info->l3 = bt->vsync + bt->vbackporch + 1; | 1443 | std_info->l3 = bt->vsync + bt->vbackporch + 1; |
1445 | 1444 | ||
1445 | std_info->vsize = V4L2_DV_BT_FRAME_HEIGHT(bt); | ||
1446 | if (bt->interlaced) { | 1446 | if (bt->interlaced) { |
1447 | if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { | 1447 | if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { |
1448 | std_info->vsize = bt->height * 2 + | ||
1449 | bt->vfrontporch + bt->vsync + bt->vbackporch + | ||
1450 | bt->il_vfrontporch + bt->il_vsync + | ||
1451 | bt->il_vbackporch; | ||
1452 | std_info->l5 = std_info->vsize/2 - | 1448 | std_info->l5 = std_info->vsize/2 - |
1453 | (bt->vfrontporch - 1); | 1449 | (bt->vfrontporch - 1); |
1454 | std_info->l7 = std_info->vsize/2 + 1; | 1450 | std_info->l7 = std_info->vsize/2 + 1; |
@@ -1462,8 +1458,6 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
1462 | return -EINVAL; | 1458 | return -EINVAL; |
1463 | } | 1459 | } |
1464 | } else { | 1460 | } else { |
1465 | std_info->vsize = bt->height + bt->vfrontporch + | ||
1466 | bt->vsync + bt->vbackporch; | ||
1467 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); | 1461 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); |
1468 | } | 1462 | } |
1469 | strncpy(std_info->name, "Custom timings BT656/1120", | 1463 | strncpy(std_info->name, "Custom timings BT656/1120", |
@@ -1618,6 +1612,102 @@ vpif_init_free_channel_objects: | |||
1618 | return err; | 1612 | return err; |
1619 | } | 1613 | } |
1620 | 1614 | ||
1615 | static int vpif_async_bound(struct v4l2_async_notifier *notifier, | ||
1616 | struct v4l2_subdev *subdev, | ||
1617 | struct v4l2_async_subdev *asd) | ||
1618 | { | ||
1619 | int i; | ||
1620 | |||
1621 | for (i = 0; i < vpif_obj.config->subdev_count; i++) | ||
1622 | if (!strcmp(vpif_obj.config->subdevinfo[i].name, | ||
1623 | subdev->name)) { | ||
1624 | vpif_obj.sd[i] = subdev; | ||
1625 | vpif_obj.sd[i]->grp_id = 1 << i; | ||
1626 | return 0; | ||
1627 | } | ||
1628 | |||
1629 | return -EINVAL; | ||
1630 | } | ||
1631 | |||
1632 | static int vpif_probe_complete(void) | ||
1633 | { | ||
1634 | struct common_obj *common; | ||
1635 | struct channel_obj *ch; | ||
1636 | int j, err, k; | ||
1637 | |||
1638 | for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { | ||
1639 | ch = vpif_obj.dev[j]; | ||
1640 | /* Initialize field of the channel objects */ | ||
1641 | atomic_set(&ch->usrs, 0); | ||
1642 | for (k = 0; k < VPIF_NUMOBJECTS; k++) { | ||
1643 | ch->common[k].numbuffers = 0; | ||
1644 | common = &ch->common[k]; | ||
1645 | common->io_usrs = 0; | ||
1646 | common->started = 0; | ||
1647 | spin_lock_init(&common->irqlock); | ||
1648 | mutex_init(&common->lock); | ||
1649 | common->numbuffers = 0; | ||
1650 | common->set_addr = NULL; | ||
1651 | common->ytop_off = 0; | ||
1652 | common->ybtm_off = 0; | ||
1653 | common->ctop_off = 0; | ||
1654 | common->cbtm_off = 0; | ||
1655 | common->cur_frm = NULL; | ||
1656 | common->next_frm = NULL; | ||
1657 | memset(&common->fmt, 0, sizeof(common->fmt)); | ||
1658 | common->numbuffers = config_params.numbuffers[k]; | ||
1659 | } | ||
1660 | ch->initialized = 0; | ||
1661 | if (vpif_obj.config->subdev_count) | ||
1662 | ch->sd = vpif_obj.sd[0]; | ||
1663 | ch->channel_id = j; | ||
1664 | if (j < 2) | ||
1665 | ch->common[VPIF_VIDEO_INDEX].numbuffers = | ||
1666 | config_params.numbuffers[ch->channel_id]; | ||
1667 | else | ||
1668 | ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; | ||
1669 | |||
1670 | memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); | ||
1671 | |||
1672 | /* Initialize prio member of channel object */ | ||
1673 | v4l2_prio_init(&ch->prio); | ||
1674 | ch->common[VPIF_VIDEO_INDEX].fmt.type = | ||
1675 | V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
1676 | ch->video_dev->lock = &common->lock; | ||
1677 | video_set_drvdata(ch->video_dev, ch); | ||
1678 | |||
1679 | /* select output 0 */ | ||
1680 | err = vpif_set_output(vpif_obj.config, ch, 0); | ||
1681 | if (err) | ||
1682 | goto probe_out; | ||
1683 | |||
1684 | /* register video device */ | ||
1685 | vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", | ||
1686 | (int)ch, (int)&ch->video_dev); | ||
1687 | |||
1688 | err = video_register_device(ch->video_dev, | ||
1689 | VFL_TYPE_GRABBER, (j ? 3 : 2)); | ||
1690 | if (err < 0) | ||
1691 | goto probe_out; | ||
1692 | } | ||
1693 | |||
1694 | return 0; | ||
1695 | |||
1696 | probe_out: | ||
1697 | for (k = 0; k < j; k++) { | ||
1698 | ch = vpif_obj.dev[k]; | ||
1699 | video_unregister_device(ch->video_dev); | ||
1700 | video_device_release(ch->video_dev); | ||
1701 | ch->video_dev = NULL; | ||
1702 | } | ||
1703 | return err; | ||
1704 | } | ||
1705 | |||
1706 | static int vpif_async_complete(struct v4l2_async_notifier *notifier) | ||
1707 | { | ||
1708 | return vpif_probe_complete(); | ||
1709 | } | ||
1710 | |||
1621 | /* | 1711 | /* |
1622 | * vpif_probe: This function creates device entries by register itself to the | 1712 | * vpif_probe: This function creates device entries by register itself to the |
1623 | * V4L2 driver and initializes fields of each channel objects | 1713 | * V4L2 driver and initializes fields of each channel objects |
@@ -1625,11 +1715,9 @@ vpif_init_free_channel_objects: | |||
1625 | static __init int vpif_probe(struct platform_device *pdev) | 1715 | static __init int vpif_probe(struct platform_device *pdev) |
1626 | { | 1716 | { |
1627 | struct vpif_subdev_info *subdevdata; | 1717 | struct vpif_subdev_info *subdevdata; |
1628 | struct vpif_display_config *config; | 1718 | int i, j = 0, err = 0; |
1629 | int i, j = 0, k, err = 0; | ||
1630 | int res_idx = 0; | 1719 | int res_idx = 0; |
1631 | struct i2c_adapter *i2c_adap; | 1720 | struct i2c_adapter *i2c_adap; |
1632 | struct common_obj *common; | ||
1633 | struct channel_obj *ch; | 1721 | struct channel_obj *ch; |
1634 | struct video_device *vfd; | 1722 | struct video_device *vfd; |
1635 | struct resource *res; | 1723 | struct resource *res; |
@@ -1708,11 +1796,9 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
1708 | size/2; | 1796 | size/2; |
1709 | } | 1797 | } |
1710 | } | 1798 | } |
1711 | 1799 | vpif_obj.config = pdev->dev.platform_data; | |
1712 | i2c_adap = i2c_get_adapter(1); | 1800 | subdev_count = vpif_obj.config->subdev_count; |
1713 | config = pdev->dev.platform_data; | 1801 | subdevdata = vpif_obj.config->subdevinfo; |
1714 | subdev_count = config->subdev_count; | ||
1715 | subdevdata = config->subdevinfo; | ||
1716 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, | 1802 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, |
1717 | GFP_KERNEL); | 1803 | GFP_KERNEL); |
1718 | if (vpif_obj.sd == NULL) { | 1804 | if (vpif_obj.sd == NULL) { |
@@ -1721,86 +1807,41 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
1721 | goto vpif_sd_error; | 1807 | goto vpif_sd_error; |
1722 | } | 1808 | } |
1723 | 1809 | ||
1724 | for (i = 0; i < subdev_count; i++) { | 1810 | if (!vpif_obj.config->asd_sizes) { |
1725 | vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, | 1811 | i2c_adap = i2c_get_adapter(1); |
1726 | i2c_adap, | 1812 | for (i = 0; i < subdev_count; i++) { |
1727 | &subdevdata[i].board_info, | 1813 | vpif_obj.sd[i] = |
1728 | NULL); | 1814 | v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, |
1729 | if (!vpif_obj.sd[i]) { | 1815 | i2c_adap, |
1730 | vpif_err("Error registering v4l2 subdevice\n"); | 1816 | &subdevdata[i]. |
1731 | err = -ENODEV; | 1817 | board_info, |
1732 | goto probe_subdev_out; | 1818 | NULL); |
1733 | } | 1819 | if (!vpif_obj.sd[i]) { |
1734 | 1820 | vpif_err("Error registering v4l2 subdevice\n"); | |
1735 | if (vpif_obj.sd[i]) | 1821 | err = -ENODEV; |
1736 | vpif_obj.sd[i]->grp_id = 1 << i; | 1822 | goto probe_subdev_out; |
1737 | } | 1823 | } |
1738 | |||
1739 | for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { | ||
1740 | ch = vpif_obj.dev[j]; | ||
1741 | /* Initialize field of the channel objects */ | ||
1742 | atomic_set(&ch->usrs, 0); | ||
1743 | for (k = 0; k < VPIF_NUMOBJECTS; k++) { | ||
1744 | ch->common[k].numbuffers = 0; | ||
1745 | common = &ch->common[k]; | ||
1746 | common->io_usrs = 0; | ||
1747 | common->started = 0; | ||
1748 | spin_lock_init(&common->irqlock); | ||
1749 | mutex_init(&common->lock); | ||
1750 | common->numbuffers = 0; | ||
1751 | common->set_addr = NULL; | ||
1752 | common->ytop_off = common->ybtm_off = 0; | ||
1753 | common->ctop_off = common->cbtm_off = 0; | ||
1754 | common->cur_frm = common->next_frm = NULL; | ||
1755 | memset(&common->fmt, 0, sizeof(common->fmt)); | ||
1756 | common->numbuffers = config_params.numbuffers[k]; | ||
1757 | 1824 | ||
1825 | if (vpif_obj.sd[i]) | ||
1826 | vpif_obj.sd[i]->grp_id = 1 << i; | ||
1827 | } | ||
1828 | vpif_probe_complete(); | ||
1829 | } else { | ||
1830 | vpif_obj.notifier.subdevs = vpif_obj.config->asd; | ||
1831 | vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; | ||
1832 | vpif_obj.notifier.bound = vpif_async_bound; | ||
1833 | vpif_obj.notifier.complete = vpif_async_complete; | ||
1834 | err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, | ||
1835 | &vpif_obj.notifier); | ||
1836 | if (err) { | ||
1837 | vpif_err("Error registering async notifier\n"); | ||
1838 | err = -EINVAL; | ||
1839 | goto probe_subdev_out; | ||
1758 | } | 1840 | } |
1759 | ch->initialized = 0; | ||
1760 | if (subdev_count) | ||
1761 | ch->sd = vpif_obj.sd[0]; | ||
1762 | ch->channel_id = j; | ||
1763 | if (j < 2) | ||
1764 | ch->common[VPIF_VIDEO_INDEX].numbuffers = | ||
1765 | config_params.numbuffers[ch->channel_id]; | ||
1766 | else | ||
1767 | ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; | ||
1768 | |||
1769 | memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); | ||
1770 | |||
1771 | /* Initialize prio member of channel object */ | ||
1772 | v4l2_prio_init(&ch->prio); | ||
1773 | ch->common[VPIF_VIDEO_INDEX].fmt.type = | ||
1774 | V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
1775 | ch->video_dev->lock = &common->lock; | ||
1776 | video_set_drvdata(ch->video_dev, ch); | ||
1777 | |||
1778 | /* select output 0 */ | ||
1779 | err = vpif_set_output(config, ch, 0); | ||
1780 | if (err) | ||
1781 | goto probe_out; | ||
1782 | |||
1783 | /* register video device */ | ||
1784 | vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", | ||
1785 | (int)ch, (int)&ch->video_dev); | ||
1786 | |||
1787 | err = video_register_device(ch->video_dev, | ||
1788 | VFL_TYPE_GRABBER, (j ? 3 : 2)); | ||
1789 | if (err < 0) | ||
1790 | goto probe_out; | ||
1791 | } | 1841 | } |
1792 | 1842 | ||
1793 | v4l2_info(&vpif_obj.v4l2_dev, | ||
1794 | " VPIF display driver initialized\n"); | ||
1795 | return 0; | 1843 | return 0; |
1796 | 1844 | ||
1797 | probe_out: | ||
1798 | for (k = 0; k < j; k++) { | ||
1799 | ch = vpif_obj.dev[k]; | ||
1800 | video_unregister_device(ch->video_dev); | ||
1801 | video_device_release(ch->video_dev); | ||
1802 | ch->video_dev = NULL; | ||
1803 | } | ||
1804 | probe_subdev_out: | 1845 | probe_subdev_out: |
1805 | kfree(vpif_obj.sd); | 1846 | kfree(vpif_obj.sd); |
1806 | vpif_sd_error: | 1847 | vpif_sd_error: |
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index 5d87fc86e580..4d0485b99a80 100644 --- a/drivers/media/platform/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h | |||
@@ -148,7 +148,8 @@ struct vpif_device { | |||
148 | struct v4l2_device v4l2_dev; | 148 | struct v4l2_device v4l2_dev; |
149 | struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS]; | 149 | struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS]; |
150 | struct v4l2_subdev **sd; | 150 | struct v4l2_subdev **sd; |
151 | 151 | struct v4l2_async_notifier notifier; | |
152 | struct vpif_display_config *config; | ||
152 | }; | 153 | }; |
153 | 154 | ||
154 | struct vpif_config_params { | 155 | struct vpif_config_params { |
diff --git a/drivers/media/platform/davinci/vpss.c b/drivers/media/platform/davinci/vpss.c index 8a2f01e344ee..31120b4a4a33 100644 --- a/drivers/media/platform/davinci/vpss.c +++ b/drivers/media/platform/davinci/vpss.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/pm_runtime.h> | 23 | #include <linux/pm_runtime.h> |
24 | #include <linux/err.h> | ||
24 | 25 | ||
25 | #include <media/davinci/vpss.h> | 26 | #include <media/davinci/vpss.h> |
26 | 27 | ||
@@ -404,9 +405,8 @@ EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size); | |||
404 | 405 | ||
405 | static int vpss_probe(struct platform_device *pdev) | 406 | static int vpss_probe(struct platform_device *pdev) |
406 | { | 407 | { |
407 | struct resource *r1, *r2; | 408 | struct resource *res; |
408 | char *platform_name; | 409 | char *platform_name; |
409 | int status; | ||
410 | 410 | ||
411 | if (!pdev->dev.platform_data) { | 411 | if (!pdev->dev.platform_data) { |
412 | dev_err(&pdev->dev, "no platform data\n"); | 412 | dev_err(&pdev->dev, "no platform data\n"); |
@@ -427,38 +427,19 @@ static int vpss_probe(struct platform_device *pdev) | |||
427 | } | 427 | } |
428 | 428 | ||
429 | dev_info(&pdev->dev, "%s vpss probed\n", platform_name); | 429 | dev_info(&pdev->dev, "%s vpss probed\n", platform_name); |
430 | r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 430 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
431 | if (!r1) | ||
432 | return -ENOENT; | ||
433 | 431 | ||
434 | r1 = request_mem_region(r1->start, resource_size(r1), r1->name); | 432 | oper_cfg.vpss_regs_base0 = devm_ioremap_resource(&pdev->dev, res); |
435 | if (!r1) | 433 | if (IS_ERR(oper_cfg.vpss_regs_base0)) |
436 | return -EBUSY; | 434 | return PTR_ERR(oper_cfg.vpss_regs_base0); |
437 | |||
438 | oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1)); | ||
439 | if (!oper_cfg.vpss_regs_base0) { | ||
440 | status = -EBUSY; | ||
441 | goto fail1; | ||
442 | } | ||
443 | 435 | ||
444 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { | 436 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { |
445 | r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 437 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
446 | if (!r2) { | 438 | |
447 | status = -ENOENT; | 439 | oper_cfg.vpss_regs_base1 = devm_ioremap_resource(&pdev->dev, |
448 | goto fail2; | 440 | res); |
449 | } | 441 | if (IS_ERR(oper_cfg.vpss_regs_base1)) |
450 | r2 = request_mem_region(r2->start, resource_size(r2), r2->name); | 442 | return PTR_ERR(oper_cfg.vpss_regs_base1); |
451 | if (!r2) { | ||
452 | status = -EBUSY; | ||
453 | goto fail2; | ||
454 | } | ||
455 | |||
456 | oper_cfg.vpss_regs_base1 = ioremap(r2->start, | ||
457 | resource_size(r2)); | ||
458 | if (!oper_cfg.vpss_regs_base1) { | ||
459 | status = -EBUSY; | ||
460 | goto fail3; | ||
461 | } | ||
462 | } | 443 | } |
463 | 444 | ||
464 | if (oper_cfg.platform == DM355) { | 445 | if (oper_cfg.platform == DM355) { |
@@ -493,30 +474,13 @@ static int vpss_probe(struct platform_device *pdev) | |||
493 | 474 | ||
494 | spin_lock_init(&oper_cfg.vpss_lock); | 475 | spin_lock_init(&oper_cfg.vpss_lock); |
495 | dev_info(&pdev->dev, "%s vpss probe success\n", platform_name); | 476 | dev_info(&pdev->dev, "%s vpss probe success\n", platform_name); |
496 | return 0; | ||
497 | 477 | ||
498 | fail3: | 478 | return 0; |
499 | release_mem_region(r2->start, resource_size(r2)); | ||
500 | fail2: | ||
501 | iounmap(oper_cfg.vpss_regs_base0); | ||
502 | fail1: | ||
503 | release_mem_region(r1->start, resource_size(r1)); | ||
504 | return status; | ||
505 | } | 479 | } |
506 | 480 | ||
507 | static int vpss_remove(struct platform_device *pdev) | 481 | static int vpss_remove(struct platform_device *pdev) |
508 | { | 482 | { |
509 | struct resource *res; | ||
510 | |||
511 | pm_runtime_disable(&pdev->dev); | 483 | pm_runtime_disable(&pdev->dev); |
512 | iounmap(oper_cfg.vpss_regs_base0); | ||
513 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
514 | release_mem_region(res->start, resource_size(res)); | ||
515 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { | ||
516 | iounmap(oper_cfg.vpss_regs_base1); | ||
517 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
518 | release_mem_region(res->start, resource_size(res)); | ||
519 | } | ||
520 | return 0; | 484 | return 0; |
521 | } | 485 | } |
522 | 486 | ||
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 559fab2a2d67..9d0cc04d7ab7 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c | |||
@@ -1122,10 +1122,14 @@ static int gsc_probe(struct platform_device *pdev) | |||
1122 | goto err_clk; | 1122 | goto err_clk; |
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | ret = gsc_register_m2m_device(gsc); | 1125 | ret = v4l2_device_register(dev, &gsc->v4l2_dev); |
1126 | if (ret) | 1126 | if (ret) |
1127 | goto err_clk; | 1127 | goto err_clk; |
1128 | 1128 | ||
1129 | ret = gsc_register_m2m_device(gsc); | ||
1130 | if (ret) | ||
1131 | goto err_v4l2; | ||
1132 | |||
1129 | platform_set_drvdata(pdev, gsc); | 1133 | platform_set_drvdata(pdev, gsc); |
1130 | pm_runtime_enable(dev); | 1134 | pm_runtime_enable(dev); |
1131 | ret = pm_runtime_get_sync(&pdev->dev); | 1135 | ret = pm_runtime_get_sync(&pdev->dev); |
@@ -1147,6 +1151,8 @@ err_pm: | |||
1147 | pm_runtime_put(dev); | 1151 | pm_runtime_put(dev); |
1148 | err_m2m: | 1152 | err_m2m: |
1149 | gsc_unregister_m2m_device(gsc); | 1153 | gsc_unregister_m2m_device(gsc); |
1154 | err_v4l2: | ||
1155 | v4l2_device_unregister(&gsc->v4l2_dev); | ||
1150 | err_clk: | 1156 | err_clk: |
1151 | gsc_clk_put(gsc); | 1157 | gsc_clk_put(gsc); |
1152 | return ret; | 1158 | return ret; |
@@ -1157,6 +1163,7 @@ static int gsc_remove(struct platform_device *pdev) | |||
1157 | struct gsc_dev *gsc = platform_get_drvdata(pdev); | 1163 | struct gsc_dev *gsc = platform_get_drvdata(pdev); |
1158 | 1164 | ||
1159 | gsc_unregister_m2m_device(gsc); | 1165 | gsc_unregister_m2m_device(gsc); |
1166 | v4l2_device_unregister(&gsc->v4l2_dev); | ||
1160 | 1167 | ||
1161 | vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); | 1168 | vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); |
1162 | pm_runtime_disable(&pdev->dev); | 1169 | pm_runtime_disable(&pdev->dev); |
@@ -1210,12 +1217,12 @@ static int gsc_resume(struct device *dev) | |||
1210 | spin_unlock_irqrestore(&gsc->slock, flags); | 1217 | spin_unlock_irqrestore(&gsc->slock, flags); |
1211 | return 0; | 1218 | return 0; |
1212 | } | 1219 | } |
1213 | gsc_hw_set_sw_reset(gsc); | ||
1214 | gsc_wait_reset(gsc); | ||
1215 | |||
1216 | spin_unlock_irqrestore(&gsc->slock, flags); | 1220 | spin_unlock_irqrestore(&gsc->slock, flags); |
1217 | 1221 | ||
1218 | return gsc_m2m_resume(gsc); | 1222 | if (!pm_runtime_suspended(dev)) |
1223 | return gsc_runtime_resume(dev); | ||
1224 | |||
1225 | return 0; | ||
1219 | } | 1226 | } |
1220 | 1227 | ||
1221 | static int gsc_suspend(struct device *dev) | 1228 | static int gsc_suspend(struct device *dev) |
@@ -1227,7 +1234,10 @@ static int gsc_suspend(struct device *dev) | |||
1227 | if (test_and_set_bit(ST_SUSPEND, &gsc->state)) | 1234 | if (test_and_set_bit(ST_SUSPEND, &gsc->state)) |
1228 | return 0; | 1235 | return 0; |
1229 | 1236 | ||
1230 | return gsc_m2m_suspend(gsc); | 1237 | if (!pm_runtime_suspended(dev)) |
1238 | return gsc_runtime_suspend(dev); | ||
1239 | |||
1240 | return 0; | ||
1231 | } | 1241 | } |
1232 | 1242 | ||
1233 | static const struct dev_pm_ops gsc_pm_ops = { | 1243 | static const struct dev_pm_ops gsc_pm_ops = { |
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h index cc19bba09bd1..76435d3bf62d 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/exynos-gsc/gsc-core.h | |||
@@ -343,6 +343,7 @@ struct gsc_dev { | |||
343 | unsigned long state; | 343 | unsigned long state; |
344 | struct vb2_alloc_ctx *alloc_ctx; | 344 | struct vb2_alloc_ctx *alloc_ctx; |
345 | struct video_device vdev; | 345 | struct video_device vdev; |
346 | struct v4l2_device v4l2_dev; | ||
346 | }; | 347 | }; |
347 | 348 | ||
348 | /** | 349 | /** |
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 40a73f7d20da..e576ff2de3de 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c | |||
@@ -751,6 +751,7 @@ int gsc_register_m2m_device(struct gsc_dev *gsc) | |||
751 | gsc->vdev.release = video_device_release_empty; | 751 | gsc->vdev.release = video_device_release_empty; |
752 | gsc->vdev.lock = &gsc->lock; | 752 | gsc->vdev.lock = &gsc->lock; |
753 | gsc->vdev.vfl_dir = VFL_DIR_M2M; | 753 | gsc->vdev.vfl_dir = VFL_DIR_M2M; |
754 | gsc->vdev.v4l2_dev = &gsc->v4l2_dev; | ||
754 | snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", | 755 | snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", |
755 | GSC_MODULE_NAME, gsc->id); | 756 | GSC_MODULE_NAME, gsc->id); |
756 | 757 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index 6489c5160ee8..3d66d88ea3a1 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c | |||
@@ -1110,6 +1110,8 @@ static int fimc_remove(struct platform_device *pdev) | |||
1110 | struct fimc_dev *fimc = platform_get_drvdata(pdev); | 1110 | struct fimc_dev *fimc = platform_get_drvdata(pdev); |
1111 | 1111 | ||
1112 | pm_runtime_disable(&pdev->dev); | 1112 | pm_runtime_disable(&pdev->dev); |
1113 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
1114 | clk_disable(fimc->clock[CLK_GATE]); | ||
1113 | pm_runtime_set_suspended(&pdev->dev); | 1115 | pm_runtime_set_suspended(&pdev->dev); |
1114 | 1116 | ||
1115 | fimc_unregister_capture_subdev(fimc); | 1117 | fimc_unregister_capture_subdev(fimc); |
diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c index 993055605214..371cad4fcce9 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c +++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c | |||
@@ -81,21 +81,46 @@ static int fimc_is_i2c_remove(struct platform_device *pdev) | |||
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
83 | 83 | ||
84 | static int fimc_is_i2c_suspend(struct device *dev) | 84 | #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) |
85 | static int fimc_is_i2c_runtime_suspend(struct device *dev) | ||
85 | { | 86 | { |
86 | struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); | 87 | struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); |
88 | |||
87 | clk_disable_unprepare(isp_i2c->clock); | 89 | clk_disable_unprepare(isp_i2c->clock); |
88 | return 0; | 90 | return 0; |
89 | } | 91 | } |
90 | 92 | ||
91 | static int fimc_is_i2c_resume(struct device *dev) | 93 | static int fimc_is_i2c_runtime_resume(struct device *dev) |
92 | { | 94 | { |
93 | struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); | 95 | struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); |
96 | |||
94 | return clk_prepare_enable(isp_i2c->clock); | 97 | return clk_prepare_enable(isp_i2c->clock); |
95 | } | 98 | } |
99 | #endif | ||
96 | 100 | ||
97 | static UNIVERSAL_DEV_PM_OPS(fimc_is_i2c_pm_ops, fimc_is_i2c_suspend, | 101 | #ifdef CONFIG_PM_SLEEP |
98 | fimc_is_i2c_resume, NULL); | 102 | static int fimc_is_i2c_suspend(struct device *dev) |
103 | { | ||
104 | if (pm_runtime_suspended(dev)) | ||
105 | return 0; | ||
106 | |||
107 | return fimc_is_i2c_runtime_suspend(dev); | ||
108 | } | ||
109 | |||
110 | static int fimc_is_i2c_resume(struct device *dev) | ||
111 | { | ||
112 | if (pm_runtime_suspended(dev)) | ||
113 | return 0; | ||
114 | |||
115 | return fimc_is_i2c_runtime_resume(dev); | ||
116 | } | ||
117 | #endif | ||
118 | |||
119 | static struct dev_pm_ops fimc_is_i2c_pm_ops = { | ||
120 | SET_RUNTIME_PM_OPS(fimc_is_i2c_runtime_suspend, | ||
121 | fimc_is_i2c_runtime_resume, NULL) | ||
122 | SET_SYSTEM_SLEEP_PM_OPS(fimc_is_i2c_suspend, fimc_is_i2c_resume) | ||
123 | }; | ||
99 | 124 | ||
100 | static const struct of_device_id fimc_is_i2c_of_match[] = { | 125 | static const struct of_device_id fimc_is_i2c_of_match[] = { |
101 | { .compatible = FIMC_IS_I2C_COMPATIBLE }, | 126 | { .compatible = FIMC_IS_I2C_COMPATIBLE }, |
diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.c b/drivers/media/platform/exynos4-is/fimc-is-param.c index c7e7f694c6ed..9bf3ddd9e028 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-param.c +++ b/drivers/media/platform/exynos4-is/fimc-is-param.c | |||
@@ -56,7 +56,7 @@ static void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is) | |||
56 | __hw_param_copy(dst, src); | 56 | __hw_param_copy(dst, src); |
57 | } | 57 | } |
58 | 58 | ||
59 | int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset) | 59 | static int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset) |
60 | { | 60 | { |
61 | struct is_param_region *par = &is->is_p_region->parameter; | 61 | struct is_param_region *par = &is->is_p_region->parameter; |
62 | struct chain_config *cfg = &is->config[is->config_index]; | 62 | struct chain_config *cfg = &is->config[is->config_index]; |
@@ -287,7 +287,7 @@ void __is_set_sensor(struct fimc_is *is, int fps) | |||
287 | fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); | 287 | fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); |
288 | } | 288 | } |
289 | 289 | ||
290 | void __is_set_init_isp_aa(struct fimc_is *is) | 290 | static void __maybe_unused __is_set_init_isp_aa(struct fimc_is *is) |
291 | { | 291 | { |
292 | struct isp_param *isp; | 292 | struct isp_param *isp; |
293 | 293 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c index 63c68ec7cfa4..f758e2694fa3 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.c +++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c | |||
@@ -96,7 +96,7 @@ int fimc_is_hw_set_param(struct fimc_is *is) | |||
96 | return 0; | 96 | return 0; |
97 | } | 97 | } |
98 | 98 | ||
99 | int fimc_is_hw_set_tune(struct fimc_is *is) | 99 | static int __maybe_unused fimc_is_hw_set_tune(struct fimc_is *is) |
100 | { | 100 | { |
101 | fimc_is_hw_wait_intmsr0_intmsd0(is); | 101 | fimc_is_hw_wait_intmsr0_intmsd0(is); |
102 | 102 | ||
@@ -236,7 +236,7 @@ int fimc_is_itf_mode_change(struct fimc_is *is) | |||
236 | fimc_is_hw_change_mode(is); | 236 | fimc_is_hw_change_mode(is); |
237 | ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1, | 237 | ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1, |
238 | FIMC_IS_CONFIG_TIMEOUT); | 238 | FIMC_IS_CONFIG_TIMEOUT); |
239 | if (!ret < 0) | 239 | if (ret < 0) |
240 | dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n", | 240 | dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n", |
241 | __func__, is->config_index); | 241 | __func__, is->config_index); |
242 | return ret; | 242 | return ret; |
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 2276fdc213c5..9770fa98d6a1 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c | |||
@@ -993,3 +993,4 @@ module_exit(fimc_is_module_exit); | |||
993 | MODULE_ALIAS("platform:" FIMC_IS_DRV_NAME); | 993 | MODULE_ALIAS("platform:" FIMC_IS_DRV_NAME); |
994 | MODULE_AUTHOR("Younghwan Joo <yhwan.joo@samsung.com>"); | 994 | MODULE_AUTHOR("Younghwan Joo <yhwan.joo@samsung.com>"); |
995 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | 995 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); |
996 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index cf520a7d7f71..d2e6cba3566d 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c | |||
@@ -672,6 +672,8 @@ int fimc_isp_subdev_create(struct fimc_isp *isp) | |||
672 | mutex_init(&isp->subdev_lock); | 672 | mutex_init(&isp->subdev_lock); |
673 | 673 | ||
674 | v4l2_subdev_init(sd, &fimc_is_subdev_ops); | 674 | v4l2_subdev_init(sd, &fimc_is_subdev_ops); |
675 | |||
676 | sd->owner = THIS_MODULE; | ||
675 | sd->grp_id = GRP_ID_FIMC_IS; | 677 | sd->grp_id = GRP_ID_FIMC_IS; |
676 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 678 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
677 | snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP"); | 679 | snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP"); |
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 08fbfedea90f..e5798f70d149 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c | |||
@@ -90,7 +90,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { | |||
90 | .name = "RAW10 (GRBG)", | 90 | .name = "RAW10 (GRBG)", |
91 | .fourcc = V4L2_PIX_FMT_SGRBG10, | 91 | .fourcc = V4L2_PIX_FMT_SGRBG10, |
92 | .colorspace = V4L2_COLORSPACE_SRGB, | 92 | .colorspace = V4L2_COLORSPACE_SRGB, |
93 | .depth = { 10 }, | 93 | .depth = { 16 }, |
94 | .color = FIMC_FMT_RAW10, | 94 | .color = FIMC_FMT_RAW10, |
95 | .memplanes = 1, | 95 | .memplanes = 1, |
96 | .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10, | 96 | .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10, |
@@ -99,7 +99,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { | |||
99 | .name = "RAW12 (GRBG)", | 99 | .name = "RAW12 (GRBG)", |
100 | .fourcc = V4L2_PIX_FMT_SGRBG12, | 100 | .fourcc = V4L2_PIX_FMT_SGRBG12, |
101 | .colorspace = V4L2_COLORSPACE_SRGB, | 101 | .colorspace = V4L2_COLORSPACE_SRGB, |
102 | .depth = { 12 }, | 102 | .depth = { 16 }, |
103 | .color = FIMC_FMT_RAW12, | 103 | .color = FIMC_FMT_RAW12, |
104 | .memplanes = 1, | 104 | .memplanes = 1, |
105 | .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12, | 105 | .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12, |
@@ -1504,16 +1504,17 @@ static int fimc_lite_probe(struct platform_device *pdev) | |||
1504 | struct resource *res; | 1504 | struct resource *res; |
1505 | int ret; | 1505 | int ret; |
1506 | 1506 | ||
1507 | if (!dev->of_node) | ||
1508 | return -ENODEV; | ||
1509 | |||
1507 | fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL); | 1510 | fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL); |
1508 | if (!fimc) | 1511 | if (!fimc) |
1509 | return -ENOMEM; | 1512 | return -ENOMEM; |
1510 | 1513 | ||
1511 | if (dev->of_node) { | 1514 | of_id = of_match_node(flite_of_match, dev->of_node); |
1512 | of_id = of_match_node(flite_of_match, dev->of_node); | 1515 | if (of_id) |
1513 | if (of_id) | 1516 | drv_data = (struct flite_drvdata *)of_id->data; |
1514 | drv_data = (struct flite_drvdata *)of_id->data; | 1517 | fimc->index = of_alias_get_id(dev->of_node, "fimc-lite"); |
1515 | fimc->index = of_alias_get_id(dev->of_node, "fimc-lite"); | ||
1516 | } | ||
1517 | 1518 | ||
1518 | if (!drv_data || fimc->index >= drv_data->num_instances || | 1519 | if (!drv_data || fimc->index >= drv_data->num_instances || |
1519 | fimc->index < 0) { | 1520 | fimc->index < 0) { |
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index f8c66b434fd6..a83511278317 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c | |||
@@ -1149,7 +1149,6 @@ static void fimc_md_put_clocks(struct fimc_md *fmd) | |||
1149 | while (--i >= 0) { | 1149 | while (--i >= 0) { |
1150 | if (IS_ERR(fmd->camclk[i].clock)) | 1150 | if (IS_ERR(fmd->camclk[i].clock)) |
1151 | continue; | 1151 | continue; |
1152 | clk_unprepare(fmd->camclk[i].clock); | ||
1153 | clk_put(fmd->camclk[i].clock); | 1152 | clk_put(fmd->camclk[i].clock); |
1154 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | 1153 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); |
1155 | } | 1154 | } |
@@ -1168,7 +1167,7 @@ static int fimc_md_get_clocks(struct fimc_md *fmd) | |||
1168 | struct device *dev = NULL; | 1167 | struct device *dev = NULL; |
1169 | char clk_name[32]; | 1168 | char clk_name[32]; |
1170 | struct clk *clock; | 1169 | struct clk *clock; |
1171 | int ret, i; | 1170 | int i, ret = 0; |
1172 | 1171 | ||
1173 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) | 1172 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) |
1174 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | 1173 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); |
@@ -1186,12 +1185,6 @@ static int fimc_md_get_clocks(struct fimc_md *fmd) | |||
1186 | ret = PTR_ERR(clock); | 1185 | ret = PTR_ERR(clock); |
1187 | break; | 1186 | break; |
1188 | } | 1187 | } |
1189 | ret = clk_prepare(clock); | ||
1190 | if (ret < 0) { | ||
1191 | clk_put(clock); | ||
1192 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | ||
1193 | break; | ||
1194 | } | ||
1195 | fmd->camclk[i].clock = clock; | 1188 | fmd->camclk[i].clock = clock; |
1196 | } | 1189 | } |
1197 | if (ret) | 1190 | if (ret) |
@@ -1248,7 +1241,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, | |||
1248 | ret = pm_runtime_get_sync(fmd->pmf); | 1241 | ret = pm_runtime_get_sync(fmd->pmf); |
1249 | if (ret < 0) | 1242 | if (ret < 0) |
1250 | return ret; | 1243 | return ret; |
1251 | ret = clk_enable(camclk->clock); | 1244 | ret = clk_prepare_enable(camclk->clock); |
1252 | dbg("Enabled camclk %d: f: %lu", si->clk_id, | 1245 | dbg("Enabled camclk %d: f: %lu", si->clk_id, |
1253 | clk_get_rate(camclk->clock)); | 1246 | clk_get_rate(camclk->clock)); |
1254 | } | 1247 | } |
@@ -1259,7 +1252,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, | |||
1259 | return 0; | 1252 | return 0; |
1260 | 1253 | ||
1261 | if (--camclk->use_count == 0) { | 1254 | if (--camclk->use_count == 0) { |
1262 | clk_disable(camclk->clock); | 1255 | clk_disable_unprepare(camclk->clock); |
1263 | pm_runtime_put(fmd->pmf); | 1256 | pm_runtime_put(fmd->pmf); |
1264 | dbg("Disabled camclk %d", si->clk_id); | 1257 | dbg("Disabled camclk %d", si->clk_id); |
1265 | } | 1258 | } |
@@ -1529,9 +1522,9 @@ static int fimc_md_probe(struct platform_device *pdev) | |||
1529 | err_unlock: | 1522 | err_unlock: |
1530 | mutex_unlock(&fmd->media_dev.graph_mutex); | 1523 | mutex_unlock(&fmd->media_dev.graph_mutex); |
1531 | err_clk: | 1524 | err_clk: |
1532 | media_device_unregister(&fmd->media_dev); | ||
1533 | fimc_md_put_clocks(fmd); | 1525 | fimc_md_put_clocks(fmd); |
1534 | fimc_md_unregister_entities(fmd); | 1526 | fimc_md_unregister_entities(fmd); |
1527 | media_device_unregister(&fmd->media_dev); | ||
1535 | err_md: | 1528 | err_md: |
1536 | v4l2_device_unregister(&fmd->v4l2_dev); | 1529 | v4l2_device_unregister(&fmd->v4l2_dev); |
1537 | return ret; | 1530 | return ret; |
@@ -1543,6 +1536,8 @@ static int fimc_md_remove(struct platform_device *pdev) | |||
1543 | 1536 | ||
1544 | if (!fmd) | 1537 | if (!fmd) |
1545 | return 0; | 1538 | return 0; |
1539 | |||
1540 | v4l2_device_unregister(&fmd->v4l2_dev); | ||
1546 | device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); | 1541 | device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); |
1547 | fimc_md_unregister_entities(fmd); | 1542 | fimc_md_unregister_entities(fmd); |
1548 | fimc_md_pipelines_free(fmd); | 1543 | fimc_md_pipelines_free(fmd); |
diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index 1f079ff33d4b..562845361246 100644 --- a/drivers/media/platform/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c | |||
@@ -399,7 +399,7 @@ static void cafe_ctlr_init(struct mcam_camera *mcam) | |||
399 | } | 399 | } |
400 | 400 | ||
401 | 401 | ||
402 | static void cafe_ctlr_power_up(struct mcam_camera *mcam) | 402 | static int cafe_ctlr_power_up(struct mcam_camera *mcam) |
403 | { | 403 | { |
404 | /* | 404 | /* |
405 | * Part one of the sensor dance: turn the global | 405 | * Part one of the sensor dance: turn the global |
@@ -414,6 +414,8 @@ static void cafe_ctlr_power_up(struct mcam_camera *mcam) | |||
414 | */ | 414 | */ |
415 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ | 415 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ |
416 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); | 416 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); |
417 | |||
418 | return 0; | ||
417 | } | 419 | } |
418 | 420 | ||
419 | static void cafe_ctlr_power_down(struct mcam_camera *mcam) | 421 | static void cafe_ctlr_power_down(struct mcam_camera *mcam) |
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 0821ed08c122..5184887b155c 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/clk.h> | ||
22 | #include <linux/videodev2.h> | 23 | #include <linux/videodev2.h> |
23 | #include <media/v4l2-device.h> | 24 | #include <media/v4l2-device.h> |
24 | #include <media/v4l2-ioctl.h> | 25 | #include <media/v4l2-ioctl.h> |
@@ -93,6 +94,9 @@ MODULE_PARM_DESC(buffer_mode, | |||
93 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ | 94 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ |
94 | #define CF_SINGLE_BUFFER 5 /* Running with a single buffer */ | 95 | #define CF_SINGLE_BUFFER 5 /* Running with a single buffer */ |
95 | #define CF_SG_RESTART 6 /* SG restart needed */ | 96 | #define CF_SG_RESTART 6 /* SG restart needed */ |
97 | #define CF_FRAME_SOF0 7 /* Frame 0 started */ | ||
98 | #define CF_FRAME_SOF1 8 | ||
99 | #define CF_FRAME_SOF2 9 | ||
96 | 100 | ||
97 | #define sensor_call(cam, o, f, args...) \ | 101 | #define sensor_call(cam, o, f, args...) \ |
98 | v4l2_subdev_call(cam->sensor, o, f, ##args) | 102 | v4l2_subdev_call(cam->sensor, o, f, ##args) |
@@ -101,6 +105,7 @@ static struct mcam_format_struct { | |||
101 | __u8 *desc; | 105 | __u8 *desc; |
102 | __u32 pixelformat; | 106 | __u32 pixelformat; |
103 | int bpp; /* Bytes per pixel */ | 107 | int bpp; /* Bytes per pixel */ |
108 | bool planar; | ||
104 | enum v4l2_mbus_pixelcode mbus_code; | 109 | enum v4l2_mbus_pixelcode mbus_code; |
105 | } mcam_formats[] = { | 110 | } mcam_formats[] = { |
106 | { | 111 | { |
@@ -108,24 +113,56 @@ static struct mcam_format_struct { | |||
108 | .pixelformat = V4L2_PIX_FMT_YUYV, | 113 | .pixelformat = V4L2_PIX_FMT_YUYV, |
109 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | 114 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, |
110 | .bpp = 2, | 115 | .bpp = 2, |
116 | .planar = false, | ||
117 | }, | ||
118 | { | ||
119 | .desc = "UYVY 4:2:2", | ||
120 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
121 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
122 | .bpp = 2, | ||
123 | .planar = false, | ||
124 | }, | ||
125 | { | ||
126 | .desc = "YUV 4:2:2 PLANAR", | ||
127 | .pixelformat = V4L2_PIX_FMT_YUV422P, | ||
128 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
129 | .bpp = 2, | ||
130 | .planar = true, | ||
131 | }, | ||
132 | { | ||
133 | .desc = "YUV 4:2:0 PLANAR", | ||
134 | .pixelformat = V4L2_PIX_FMT_YUV420, | ||
135 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
136 | .bpp = 2, | ||
137 | .planar = true, | ||
138 | }, | ||
139 | { | ||
140 | .desc = "YVU 4:2:0 PLANAR", | ||
141 | .pixelformat = V4L2_PIX_FMT_YVU420, | ||
142 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
143 | .bpp = 2, | ||
144 | .planar = true, | ||
111 | }, | 145 | }, |
112 | { | 146 | { |
113 | .desc = "RGB 444", | 147 | .desc = "RGB 444", |
114 | .pixelformat = V4L2_PIX_FMT_RGB444, | 148 | .pixelformat = V4L2_PIX_FMT_RGB444, |
115 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, | 149 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, |
116 | .bpp = 2, | 150 | .bpp = 2, |
151 | .planar = false, | ||
117 | }, | 152 | }, |
118 | { | 153 | { |
119 | .desc = "RGB 565", | 154 | .desc = "RGB 565", |
120 | .pixelformat = V4L2_PIX_FMT_RGB565, | 155 | .pixelformat = V4L2_PIX_FMT_RGB565, |
121 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | 156 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, |
122 | .bpp = 2, | 157 | .bpp = 2, |
158 | .planar = false, | ||
123 | }, | 159 | }, |
124 | { | 160 | { |
125 | .desc = "Raw RGB Bayer", | 161 | .desc = "Raw RGB Bayer", |
126 | .pixelformat = V4L2_PIX_FMT_SBGGR8, | 162 | .pixelformat = V4L2_PIX_FMT_SBGGR8, |
127 | .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8, | 163 | .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8, |
128 | .bpp = 1 | 164 | .bpp = 1, |
165 | .planar = false, | ||
129 | }, | 166 | }, |
130 | }; | 167 | }; |
131 | #define N_MCAM_FMTS ARRAY_SIZE(mcam_formats) | 168 | #define N_MCAM_FMTS ARRAY_SIZE(mcam_formats) |
@@ -168,6 +205,12 @@ struct mcam_dma_desc { | |||
168 | u32 segment_len; | 205 | u32 segment_len; |
169 | }; | 206 | }; |
170 | 207 | ||
208 | struct yuv_pointer_t { | ||
209 | dma_addr_t y; | ||
210 | dma_addr_t u; | ||
211 | dma_addr_t v; | ||
212 | }; | ||
213 | |||
171 | /* | 214 | /* |
172 | * Our buffer type for working with videobuf2. Note that the vb2 | 215 | * Our buffer type for working with videobuf2. Note that the vb2 |
173 | * developers have decreed that struct vb2_buffer must be at the | 216 | * developers have decreed that struct vb2_buffer must be at the |
@@ -179,6 +222,7 @@ struct mcam_vb_buffer { | |||
179 | struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */ | 222 | struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */ |
180 | dma_addr_t dma_desc_pa; /* Descriptor physical address */ | 223 | dma_addr_t dma_desc_pa; /* Descriptor physical address */ |
181 | int dma_desc_nent; /* Number of mapped descriptors */ | 224 | int dma_desc_nent; /* Number of mapped descriptors */ |
225 | struct yuv_pointer_t yuv_p; | ||
182 | }; | 226 | }; |
183 | 227 | ||
184 | static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb) | 228 | static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb) |
@@ -219,8 +263,10 @@ static void mcam_reset_buffers(struct mcam_camera *cam) | |||
219 | int i; | 263 | int i; |
220 | 264 | ||
221 | cam->next_buf = -1; | 265 | cam->next_buf = -1; |
222 | for (i = 0; i < cam->nbufs; i++) | 266 | for (i = 0; i < cam->nbufs; i++) { |
223 | clear_bit(i, &cam->flags); | 267 | clear_bit(i, &cam->flags); |
268 | clear_bit(CF_FRAME_SOF0 + i, &cam->flags); | ||
269 | } | ||
224 | } | 270 | } |
225 | 271 | ||
226 | static inline int mcam_needs_config(struct mcam_camera *cam) | 272 | static inline int mcam_needs_config(struct mcam_camera *cam) |
@@ -253,6 +299,45 @@ static void mcam_ctlr_stop(struct mcam_camera *cam) | |||
253 | mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); | 299 | mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); |
254 | } | 300 | } |
255 | 301 | ||
302 | static void mcam_enable_mipi(struct mcam_camera *mcam) | ||
303 | { | ||
304 | /* Using MIPI mode and enable MIPI */ | ||
305 | cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x, DPHY6=0x%x\n", | ||
306 | mcam->dphy[0], mcam->dphy[1], mcam->dphy[2]); | ||
307 | mcam_reg_write(mcam, REG_CSI2_DPHY3, mcam->dphy[0]); | ||
308 | mcam_reg_write(mcam, REG_CSI2_DPHY5, mcam->dphy[1]); | ||
309 | mcam_reg_write(mcam, REG_CSI2_DPHY6, mcam->dphy[2]); | ||
310 | |||
311 | if (!mcam->mipi_enabled) { | ||
312 | if (mcam->lane > 4 || mcam->lane <= 0) { | ||
313 | cam_warn(mcam, "lane number error\n"); | ||
314 | mcam->lane = 1; /* set the default value */ | ||
315 | } | ||
316 | /* | ||
317 | * 0x41 actives 1 lane | ||
318 | * 0x43 actives 2 lanes | ||
319 | * 0x45 actives 3 lanes (never happen) | ||
320 | * 0x47 actives 4 lanes | ||
321 | */ | ||
322 | mcam_reg_write(mcam, REG_CSI2_CTRL0, | ||
323 | CSI2_C0_MIPI_EN | CSI2_C0_ACT_LANE(mcam->lane)); | ||
324 | mcam_reg_write(mcam, REG_CLKCTRL, | ||
325 | (mcam->mclk_src << 29) | mcam->mclk_div); | ||
326 | |||
327 | mcam->mipi_enabled = true; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | static void mcam_disable_mipi(struct mcam_camera *mcam) | ||
332 | { | ||
333 | /* Using Parallel mode or disable MIPI */ | ||
334 | mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x0); | ||
335 | mcam_reg_write(mcam, REG_CSI2_DPHY3, 0x0); | ||
336 | mcam_reg_write(mcam, REG_CSI2_DPHY5, 0x0); | ||
337 | mcam_reg_write(mcam, REG_CSI2_DPHY6, 0x0); | ||
338 | mcam->mipi_enabled = false; | ||
339 | } | ||
340 | |||
256 | /* ------------------------------------------------------------------- */ | 341 | /* ------------------------------------------------------------------- */ |
257 | 342 | ||
258 | #ifdef MCAM_MODE_VMALLOC | 343 | #ifdef MCAM_MODE_VMALLOC |
@@ -425,6 +510,15 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam) | |||
425 | /* | 510 | /* |
426 | * DMA-contiguous code. | 511 | * DMA-contiguous code. |
427 | */ | 512 | */ |
513 | |||
514 | static bool mcam_fmt_is_planar(__u32 pfmt) | ||
515 | { | ||
516 | struct mcam_format_struct *f; | ||
517 | |||
518 | f = mcam_find_format(pfmt); | ||
519 | return f->planar; | ||
520 | } | ||
521 | |||
428 | /* | 522 | /* |
429 | * Set up a contiguous buffer for the given frame. Here also is where | 523 | * Set up a contiguous buffer for the given frame. Here also is where |
430 | * the underrun strategy is set: if there is no buffer available, reuse | 524 | * the underrun strategy is set: if there is no buffer available, reuse |
@@ -436,27 +530,58 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam) | |||
436 | static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) | 530 | static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) |
437 | { | 531 | { |
438 | struct mcam_vb_buffer *buf; | 532 | struct mcam_vb_buffer *buf; |
533 | struct v4l2_pix_format *fmt = &cam->pix_format; | ||
534 | dma_addr_t dma_handle; | ||
535 | u32 pixel_count = fmt->width * fmt->height; | ||
536 | struct vb2_buffer *vb; | ||
537 | |||
439 | /* | 538 | /* |
440 | * If there are no available buffers, go into single mode | 539 | * If there are no available buffers, go into single mode |
441 | */ | 540 | */ |
442 | if (list_empty(&cam->buffers)) { | 541 | if (list_empty(&cam->buffers)) { |
443 | buf = cam->vb_bufs[frame ^ 0x1]; | 542 | buf = cam->vb_bufs[frame ^ 0x1]; |
444 | cam->vb_bufs[frame] = buf; | ||
445 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, | ||
446 | vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0)); | ||
447 | set_bit(CF_SINGLE_BUFFER, &cam->flags); | 543 | set_bit(CF_SINGLE_BUFFER, &cam->flags); |
448 | cam->frame_state.singles++; | 544 | cam->frame_state.singles++; |
449 | return; | 545 | } else { |
546 | /* | ||
547 | * OK, we have a buffer we can use. | ||
548 | */ | ||
549 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, | ||
550 | queue); | ||
551 | list_del_init(&buf->queue); | ||
552 | clear_bit(CF_SINGLE_BUFFER, &cam->flags); | ||
450 | } | 553 | } |
451 | /* | 554 | |
452 | * OK, we have a buffer we can use. | ||
453 | */ | ||
454 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); | ||
455 | list_del_init(&buf->queue); | ||
456 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, | ||
457 | vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0)); | ||
458 | cam->vb_bufs[frame] = buf; | 555 | cam->vb_bufs[frame] = buf; |
459 | clear_bit(CF_SINGLE_BUFFER, &cam->flags); | 556 | vb = &buf->vb_buf; |
557 | |||
558 | dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0); | ||
559 | buf->yuv_p.y = dma_handle; | ||
560 | |||
561 | switch (cam->pix_format.pixelformat) { | ||
562 | case V4L2_PIX_FMT_YUV422P: | ||
563 | buf->yuv_p.u = buf->yuv_p.y + pixel_count; | ||
564 | buf->yuv_p.v = buf->yuv_p.u + pixel_count / 2; | ||
565 | break; | ||
566 | case V4L2_PIX_FMT_YUV420: | ||
567 | buf->yuv_p.u = buf->yuv_p.y + pixel_count; | ||
568 | buf->yuv_p.v = buf->yuv_p.u + pixel_count / 4; | ||
569 | break; | ||
570 | case V4L2_PIX_FMT_YVU420: | ||
571 | buf->yuv_p.v = buf->yuv_p.y + pixel_count; | ||
572 | buf->yuv_p.u = buf->yuv_p.v + pixel_count / 4; | ||
573 | break; | ||
574 | default: | ||
575 | break; | ||
576 | } | ||
577 | |||
578 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y); | ||
579 | if (mcam_fmt_is_planar(fmt->pixelformat)) { | ||
580 | mcam_reg_write(cam, frame == 0 ? | ||
581 | REG_U0BAR : REG_U1BAR, buf->yuv_p.u); | ||
582 | mcam_reg_write(cam, frame == 0 ? | ||
583 | REG_V0BAR : REG_V1BAR, buf->yuv_p.v); | ||
584 | } | ||
460 | } | 585 | } |
461 | 586 | ||
462 | /* | 587 | /* |
@@ -614,48 +739,90 @@ static inline void mcam_sg_restart(struct mcam_camera *cam) | |||
614 | */ | 739 | */ |
615 | static void mcam_ctlr_image(struct mcam_camera *cam) | 740 | static void mcam_ctlr_image(struct mcam_camera *cam) |
616 | { | 741 | { |
617 | int imgsz; | ||
618 | struct v4l2_pix_format *fmt = &cam->pix_format; | 742 | struct v4l2_pix_format *fmt = &cam->pix_format; |
743 | u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w; | ||
744 | |||
745 | cam_dbg(cam, "camera: bytesperline = %d; height = %d\n", | ||
746 | fmt->bytesperline, fmt->sizeimage / fmt->bytesperline); | ||
747 | imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK; | ||
748 | imgsz_w = (fmt->width * 2) & IMGSZ_H_MASK; | ||
749 | |||
750 | switch (fmt->pixelformat) { | ||
751 | case V4L2_PIX_FMT_YUYV: | ||
752 | case V4L2_PIX_FMT_UYVY: | ||
753 | widthy = fmt->width * 2; | ||
754 | widthuv = 0; | ||
755 | break; | ||
756 | case V4L2_PIX_FMT_JPEG: | ||
757 | imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT; | ||
758 | widthy = fmt->bytesperline; | ||
759 | widthuv = 0; | ||
760 | break; | ||
761 | case V4L2_PIX_FMT_YUV422P: | ||
762 | case V4L2_PIX_FMT_YUV420: | ||
763 | case V4L2_PIX_FMT_YVU420: | ||
764 | widthy = fmt->width; | ||
765 | widthuv = fmt->width / 2; | ||
766 | break; | ||
767 | default: | ||
768 | widthy = fmt->bytesperline; | ||
769 | widthuv = 0; | ||
770 | } | ||
771 | |||
772 | mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy, | ||
773 | IMGP_YP_MASK | IMGP_UVP_MASK); | ||
774 | mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w); | ||
775 | mcam_reg_write(cam, REG_IMGOFFSET, 0x0); | ||
619 | 776 | ||
620 | imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) | | ||
621 | (fmt->bytesperline & IMGSZ_H_MASK); | ||
622 | mcam_reg_write(cam, REG_IMGSIZE, imgsz); | ||
623 | mcam_reg_write(cam, REG_IMGOFFSET, 0); | ||
624 | /* YPITCH just drops the last two bits */ | ||
625 | mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline, | ||
626 | IMGP_YP_MASK); | ||
627 | /* | 777 | /* |
628 | * Tell the controller about the image format we are using. | 778 | * Tell the controller about the image format we are using. |
629 | */ | 779 | */ |
630 | switch (cam->pix_format.pixelformat) { | 780 | switch (fmt->pixelformat) { |
781 | case V4L2_PIX_FMT_YUV422P: | ||
782 | mcam_reg_write_mask(cam, REG_CTRL0, | ||
783 | C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK); | ||
784 | break; | ||
785 | case V4L2_PIX_FMT_YUV420: | ||
786 | case V4L2_PIX_FMT_YVU420: | ||
787 | mcam_reg_write_mask(cam, REG_CTRL0, | ||
788 | C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK); | ||
789 | break; | ||
631 | case V4L2_PIX_FMT_YUYV: | 790 | case V4L2_PIX_FMT_YUYV: |
632 | mcam_reg_write_mask(cam, REG_CTRL0, | 791 | mcam_reg_write_mask(cam, REG_CTRL0, |
633 | C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV, | 792 | C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK); |
634 | C0_DF_MASK); | 793 | break; |
635 | break; | 794 | case V4L2_PIX_FMT_UYVY: |
636 | 795 | mcam_reg_write_mask(cam, REG_CTRL0, | |
796 | C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK); | ||
797 | break; | ||
798 | case V4L2_PIX_FMT_JPEG: | ||
799 | mcam_reg_write_mask(cam, REG_CTRL0, | ||
800 | C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK); | ||
801 | break; | ||
637 | case V4L2_PIX_FMT_RGB444: | 802 | case V4L2_PIX_FMT_RGB444: |
638 | mcam_reg_write_mask(cam, REG_CTRL0, | 803 | mcam_reg_write_mask(cam, REG_CTRL0, |
639 | C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB, | 804 | C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK); |
640 | C0_DF_MASK); | ||
641 | /* Alpha value? */ | 805 | /* Alpha value? */ |
642 | break; | 806 | break; |
643 | |||
644 | case V4L2_PIX_FMT_RGB565: | 807 | case V4L2_PIX_FMT_RGB565: |
645 | mcam_reg_write_mask(cam, REG_CTRL0, | 808 | mcam_reg_write_mask(cam, REG_CTRL0, |
646 | C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR, | 809 | C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK); |
647 | C0_DF_MASK); | 810 | break; |
648 | break; | ||
649 | |||
650 | default: | 811 | default: |
651 | cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat); | 812 | cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat); |
652 | break; | 813 | break; |
653 | } | 814 | } |
815 | |||
654 | /* | 816 | /* |
655 | * Make sure it knows we want to use hsync/vsync. | 817 | * Make sure it knows we want to use hsync/vsync. |
656 | */ | 818 | */ |
657 | mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, | 819 | mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK); |
658 | C0_SIFM_MASK); | 820 | /* |
821 | * This field controls the generation of EOF(DVP only) | ||
822 | */ | ||
823 | if (cam->bus_type != V4L2_MBUS_CSI2) | ||
824 | mcam_reg_set_bit(cam, REG_CTRL0, | ||
825 | C0_EOF_VSYNC | C0_VEDGE_CTRL); | ||
659 | } | 826 | } |
660 | 827 | ||
661 | 828 | ||
@@ -753,15 +920,21 @@ static void mcam_ctlr_stop_dma(struct mcam_camera *cam) | |||
753 | /* | 920 | /* |
754 | * Power up and down. | 921 | * Power up and down. |
755 | */ | 922 | */ |
756 | static void mcam_ctlr_power_up(struct mcam_camera *cam) | 923 | static int mcam_ctlr_power_up(struct mcam_camera *cam) |
757 | { | 924 | { |
758 | unsigned long flags; | 925 | unsigned long flags; |
926 | int ret; | ||
759 | 927 | ||
760 | spin_lock_irqsave(&cam->dev_lock, flags); | 928 | spin_lock_irqsave(&cam->dev_lock, flags); |
761 | cam->plat_power_up(cam); | 929 | ret = cam->plat_power_up(cam); |
930 | if (ret) { | ||
931 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
932 | return ret; | ||
933 | } | ||
762 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | 934 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); |
763 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 935 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
764 | msleep(5); /* Just to be sure */ | 936 | msleep(5); /* Just to be sure */ |
937 | return 0; | ||
765 | } | 938 | } |
766 | 939 | ||
767 | static void mcam_ctlr_power_down(struct mcam_camera *cam) | 940 | static void mcam_ctlr_power_down(struct mcam_camera *cam) |
@@ -869,6 +1042,17 @@ static int mcam_read_setup(struct mcam_camera *cam) | |||
869 | spin_lock_irqsave(&cam->dev_lock, flags); | 1042 | spin_lock_irqsave(&cam->dev_lock, flags); |
870 | clear_bit(CF_DMA_ACTIVE, &cam->flags); | 1043 | clear_bit(CF_DMA_ACTIVE, &cam->flags); |
871 | mcam_reset_buffers(cam); | 1044 | mcam_reset_buffers(cam); |
1045 | /* | ||
1046 | * Update CSI2_DPHY value | ||
1047 | */ | ||
1048 | if (cam->calc_dphy) | ||
1049 | cam->calc_dphy(cam); | ||
1050 | cam_dbg(cam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n", | ||
1051 | cam->dphy[0], cam->dphy[1], cam->dphy[2]); | ||
1052 | if (cam->bus_type == V4L2_MBUS_CSI2) | ||
1053 | mcam_enable_mipi(cam); | ||
1054 | else | ||
1055 | mcam_disable_mipi(cam); | ||
872 | mcam_ctlr_irq_enable(cam); | 1056 | mcam_ctlr_irq_enable(cam); |
873 | cam->state = S_STREAMING; | 1057 | cam->state = S_STREAMING; |
874 | if (!test_bit(CF_SG_RESTART, &cam->flags)) | 1058 | if (!test_bit(CF_SG_RESTART, &cam->flags)) |
@@ -943,6 +1127,7 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq) | |||
943 | static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count) | 1127 | static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count) |
944 | { | 1128 | { |
945 | struct mcam_camera *cam = vb2_get_drv_priv(vq); | 1129 | struct mcam_camera *cam = vb2_get_drv_priv(vq); |
1130 | unsigned int frame; | ||
946 | 1131 | ||
947 | if (cam->state != S_IDLE) { | 1132 | if (cam->state != S_IDLE) { |
948 | INIT_LIST_HEAD(&cam->buffers); | 1133 | INIT_LIST_HEAD(&cam->buffers); |
@@ -960,6 +1145,14 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
960 | cam->state = S_BUFWAIT; | 1145 | cam->state = S_BUFWAIT; |
961 | return 0; | 1146 | return 0; |
962 | } | 1147 | } |
1148 | |||
1149 | /* | ||
1150 | * Ensure clear the left over frame flags | ||
1151 | * before every really start streaming | ||
1152 | */ | ||
1153 | for (frame = 0; frame < cam->nbufs; frame++) | ||
1154 | clear_bit(CF_FRAME_SOF0 + frame, &cam->flags); | ||
1155 | |||
963 | return mcam_read_setup(cam); | 1156 | return mcam_read_setup(cam); |
964 | } | 1157 | } |
965 | 1158 | ||
@@ -977,6 +1170,12 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq) | |||
977 | return -EINVAL; | 1170 | return -EINVAL; |
978 | mcam_ctlr_stop_dma(cam); | 1171 | mcam_ctlr_stop_dma(cam); |
979 | /* | 1172 | /* |
1173 | * Reset the CCIC PHY after stopping streaming, | ||
1174 | * otherwise, the CCIC may be unstable. | ||
1175 | */ | ||
1176 | if (cam->ctlr_reset) | ||
1177 | cam->ctlr_reset(cam); | ||
1178 | /* | ||
980 | * VB2 reclaims the buffers, so we need to forget | 1179 | * VB2 reclaims the buffers, so we need to forget |
981 | * about them. | 1180 | * about them. |
982 | */ | 1181 | */ |
@@ -1087,6 +1286,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) | |||
1087 | #ifdef MCAM_MODE_DMA_CONTIG | 1286 | #ifdef MCAM_MODE_DMA_CONTIG |
1088 | vq->ops = &mcam_vb2_ops; | 1287 | vq->ops = &mcam_vb2_ops; |
1089 | vq->mem_ops = &vb2_dma_contig_memops; | 1288 | vq->mem_ops = &vb2_dma_contig_memops; |
1289 | vq->buf_struct_size = sizeof(struct mcam_vb_buffer); | ||
1090 | cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev); | 1290 | cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev); |
1091 | vq->io_modes = VB2_MMAP | VB2_USERPTR; | 1291 | vq->io_modes = VB2_MMAP | VB2_USERPTR; |
1092 | cam->dma_setup = mcam_ctlr_dma_contig; | 1292 | cam->dma_setup = mcam_ctlr_dma_contig; |
@@ -1097,6 +1297,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) | |||
1097 | #ifdef MCAM_MODE_DMA_SG | 1297 | #ifdef MCAM_MODE_DMA_SG |
1098 | vq->ops = &mcam_vb2_sg_ops; | 1298 | vq->ops = &mcam_vb2_sg_ops; |
1099 | vq->mem_ops = &vb2_dma_sg_memops; | 1299 | vq->mem_ops = &vb2_dma_sg_memops; |
1300 | vq->buf_struct_size = sizeof(struct mcam_vb_buffer); | ||
1100 | vq->io_modes = VB2_MMAP | VB2_USERPTR; | 1301 | vq->io_modes = VB2_MMAP | VB2_USERPTR; |
1101 | cam->dma_setup = mcam_ctlr_dma_sg; | 1302 | cam->dma_setup = mcam_ctlr_dma_sg; |
1102 | cam->frame_complete = mcam_dma_sg_done; | 1303 | cam->frame_complete = mcam_dma_sg_done; |
@@ -1247,7 +1448,15 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv, | |||
1247 | ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt); | 1448 | ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt); |
1248 | mutex_unlock(&cam->s_mutex); | 1449 | mutex_unlock(&cam->s_mutex); |
1249 | v4l2_fill_pix_format(pix, &mbus_fmt); | 1450 | v4l2_fill_pix_format(pix, &mbus_fmt); |
1250 | pix->bytesperline = pix->width * f->bpp; | 1451 | switch (f->pixelformat) { |
1452 | case V4L2_PIX_FMT_YUV420: | ||
1453 | case V4L2_PIX_FMT_YVU420: | ||
1454 | pix->bytesperline = pix->width * 3 / 2; | ||
1455 | break; | ||
1456 | default: | ||
1457 | pix->bytesperline = pix->width * f->bpp; | ||
1458 | break; | ||
1459 | } | ||
1251 | pix->sizeimage = pix->height * pix->bytesperline; | 1460 | pix->sizeimage = pix->height * pix->bytesperline; |
1252 | return ret; | 1461 | return ret; |
1253 | } | 1462 | } |
@@ -1475,7 +1684,9 @@ static int mcam_v4l_open(struct file *filp) | |||
1475 | ret = mcam_setup_vb2(cam); | 1684 | ret = mcam_setup_vb2(cam); |
1476 | if (ret) | 1685 | if (ret) |
1477 | goto out; | 1686 | goto out; |
1478 | mcam_ctlr_power_up(cam); | 1687 | ret = mcam_ctlr_power_up(cam); |
1688 | if (ret) | ||
1689 | goto out; | ||
1479 | __mcam_cam_reset(cam); | 1690 | __mcam_cam_reset(cam); |
1480 | mcam_set_config_needed(cam, 1); | 1691 | mcam_set_config_needed(cam, 1); |
1481 | } | 1692 | } |
@@ -1498,10 +1709,12 @@ static int mcam_v4l_release(struct file *filp) | |||
1498 | if (cam->users == 0) { | 1709 | if (cam->users == 0) { |
1499 | mcam_ctlr_stop_dma(cam); | 1710 | mcam_ctlr_stop_dma(cam); |
1500 | mcam_cleanup_vb2(cam); | 1711 | mcam_cleanup_vb2(cam); |
1712 | mcam_disable_mipi(cam); | ||
1501 | mcam_ctlr_power_down(cam); | 1713 | mcam_ctlr_power_down(cam); |
1502 | if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) | 1714 | if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) |
1503 | mcam_free_dma_bufs(cam); | 1715 | mcam_free_dma_bufs(cam); |
1504 | } | 1716 | } |
1717 | |||
1505 | mutex_unlock(&cam->s_mutex); | 1718 | mutex_unlock(&cam->s_mutex); |
1506 | return 0; | 1719 | return 0; |
1507 | } | 1720 | } |
@@ -1617,9 +1830,11 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs) | |||
1617 | * each time. | 1830 | * each time. |
1618 | */ | 1831 | */ |
1619 | for (frame = 0; frame < cam->nbufs; frame++) | 1832 | for (frame = 0; frame < cam->nbufs; frame++) |
1620 | if (irqs & (IRQ_EOF0 << frame)) { | 1833 | if (irqs & (IRQ_EOF0 << frame) && |
1834 | test_bit(CF_FRAME_SOF0 + frame, &cam->flags)) { | ||
1621 | mcam_frame_complete(cam, frame); | 1835 | mcam_frame_complete(cam, frame); |
1622 | handled = 1; | 1836 | handled = 1; |
1837 | clear_bit(CF_FRAME_SOF0 + frame, &cam->flags); | ||
1623 | if (cam->buffer_mode == B_DMA_sg) | 1838 | if (cam->buffer_mode == B_DMA_sg) |
1624 | break; | 1839 | break; |
1625 | } | 1840 | } |
@@ -1628,9 +1843,15 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs) | |||
1628 | * code assumes that we won't get multiple frame interrupts | 1843 | * code assumes that we won't get multiple frame interrupts |
1629 | * at once; may want to rethink that. | 1844 | * at once; may want to rethink that. |
1630 | */ | 1845 | */ |
1631 | if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) { | 1846 | for (frame = 0; frame < cam->nbufs; frame++) { |
1847 | if (irqs & (IRQ_SOF0 << frame)) { | ||
1848 | set_bit(CF_FRAME_SOF0 + frame, &cam->flags); | ||
1849 | handled = IRQ_HANDLED; | ||
1850 | } | ||
1851 | } | ||
1852 | |||
1853 | if (handled == IRQ_HANDLED) { | ||
1632 | set_bit(CF_DMA_ACTIVE, &cam->flags); | 1854 | set_bit(CF_DMA_ACTIVE, &cam->flags); |
1633 | handled = 1; | ||
1634 | if (cam->buffer_mode == B_DMA_sg) | 1855 | if (cam->buffer_mode == B_DMA_sg) |
1635 | mcam_ctlr_stop(cam); | 1856 | mcam_ctlr_stop(cam); |
1636 | } | 1857 | } |
@@ -1787,7 +2008,11 @@ int mccic_resume(struct mcam_camera *cam) | |||
1787 | 2008 | ||
1788 | mutex_lock(&cam->s_mutex); | 2009 | mutex_lock(&cam->s_mutex); |
1789 | if (cam->users > 0) { | 2010 | if (cam->users > 0) { |
1790 | mcam_ctlr_power_up(cam); | 2011 | ret = mcam_ctlr_power_up(cam); |
2012 | if (ret) { | ||
2013 | mutex_unlock(&cam->s_mutex); | ||
2014 | return ret; | ||
2015 | } | ||
1791 | __mcam_cam_reset(cam); | 2016 | __mcam_cam_reset(cam); |
1792 | } else { | 2017 | } else { |
1793 | mcam_ctlr_power_down(cam); | 2018 | mcam_ctlr_power_down(cam); |
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index 520c8ded9443..e0e628cb98f9 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h | |||
@@ -88,6 +88,8 @@ struct mcam_frame_state { | |||
88 | unsigned int delivered; | 88 | unsigned int delivered; |
89 | }; | 89 | }; |
90 | 90 | ||
91 | #define NR_MCAM_CLK 3 | ||
92 | |||
91 | /* | 93 | /* |
92 | * A description of one of our devices. | 94 | * A description of one of our devices. |
93 | * Locking: controlled by s_mutex. Certain fields, however, require | 95 | * Locking: controlled by s_mutex. Certain fields, however, require |
@@ -108,11 +110,33 @@ struct mcam_camera { | |||
108 | short int clock_speed; /* Sensor clock speed, default 30 */ | 110 | short int clock_speed; /* Sensor clock speed, default 30 */ |
109 | short int use_smbus; /* SMBUS or straight I2c? */ | 111 | short int use_smbus; /* SMBUS or straight I2c? */ |
110 | enum mcam_buffer_mode buffer_mode; | 112 | enum mcam_buffer_mode buffer_mode; |
113 | |||
114 | int mclk_min; /* The minimal value of mclk */ | ||
115 | int mclk_src; /* which clock source the mclk derives from */ | ||
116 | int mclk_div; /* Clock Divider Value for MCLK */ | ||
117 | |||
118 | int ccic_id; | ||
119 | enum v4l2_mbus_type bus_type; | ||
120 | /* MIPI support */ | ||
121 | /* The dphy config value, allocated in board file | ||
122 | * dphy[0]: DPHY3 | ||
123 | * dphy[1]: DPHY5 | ||
124 | * dphy[2]: DPHY6 | ||
125 | */ | ||
126 | int *dphy; | ||
127 | bool mipi_enabled; /* flag whether mipi is enabled already */ | ||
128 | int lane; /* lane number */ | ||
129 | |||
130 | /* clock tree support */ | ||
131 | struct clk *clk[NR_MCAM_CLK]; | ||
132 | |||
111 | /* | 133 | /* |
112 | * Callbacks from the core to the platform code. | 134 | * Callbacks from the core to the platform code. |
113 | */ | 135 | */ |
114 | void (*plat_power_up) (struct mcam_camera *cam); | 136 | int (*plat_power_up) (struct mcam_camera *cam); |
115 | void (*plat_power_down) (struct mcam_camera *cam); | 137 | void (*plat_power_down) (struct mcam_camera *cam); |
138 | void (*calc_dphy) (struct mcam_camera *cam); | ||
139 | void (*ctlr_reset) (struct mcam_camera *cam); | ||
116 | 140 | ||
117 | /* | 141 | /* |
118 | * Everything below here is private to the mcam core and | 142 | * Everything below here is private to the mcam core and |
@@ -225,6 +249,23 @@ int mccic_resume(struct mcam_camera *cam); | |||
225 | #define REG_Y0BAR 0x00 | 249 | #define REG_Y0BAR 0x00 |
226 | #define REG_Y1BAR 0x04 | 250 | #define REG_Y1BAR 0x04 |
227 | #define REG_Y2BAR 0x08 | 251 | #define REG_Y2BAR 0x08 |
252 | #define REG_U0BAR 0x0c | ||
253 | #define REG_U1BAR 0x10 | ||
254 | #define REG_U2BAR 0x14 | ||
255 | #define REG_V0BAR 0x18 | ||
256 | #define REG_V1BAR 0x1C | ||
257 | #define REG_V2BAR 0x20 | ||
258 | |||
259 | /* | ||
260 | * register definitions for MIPI support | ||
261 | */ | ||
262 | #define REG_CSI2_CTRL0 0x100 | ||
263 | #define CSI2_C0_MIPI_EN (0x1 << 0) | ||
264 | #define CSI2_C0_ACT_LANE(n) ((n-1) << 1) | ||
265 | #define REG_CSI2_DPHY3 0x12c | ||
266 | #define REG_CSI2_DPHY5 0x134 | ||
267 | #define REG_CSI2_DPHY6 0x138 | ||
268 | |||
228 | /* ... */ | 269 | /* ... */ |
229 | 270 | ||
230 | #define REG_IMGPITCH 0x24 /* Image pitch register */ | 271 | #define REG_IMGPITCH 0x24 /* Image pitch register */ |
@@ -293,13 +334,16 @@ int mccic_resume(struct mcam_camera *cam); | |||
293 | #define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ | 334 | #define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ |
294 | #define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ | 335 | #define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ |
295 | /* Bayer bits 18,19 if needed */ | 336 | /* Bayer bits 18,19 if needed */ |
337 | #define C0_EOF_VSYNC 0x00400000 /* Generate EOF by VSYNC */ | ||
338 | #define C0_VEDGE_CTRL 0x00800000 /* Detect falling edge of VSYNC */ | ||
296 | #define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ | 339 | #define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ |
297 | #define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ | 340 | #define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ |
298 | #define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ | 341 | #define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ |
299 | #define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ | 342 | #define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ |
300 | #define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ | 343 | /* SIFMODE */ |
301 | #define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ | 344 | #define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ |
302 | #define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ | 345 | #define C0_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ |
346 | #define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ | ||
303 | 347 | ||
304 | /* Bits below C1_444ALPHA are not present in Cafe */ | 348 | /* Bits below C1_444ALPHA are not present in Cafe */ |
305 | #define REG_CTRL1 0x40 /* Control 1 */ | 349 | #define REG_CTRL1 0x40 /* Control 1 */ |
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index a634888271cd..b5a19af5c587 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/list.h> | 27 | #include <linux/list.h> |
28 | #include <linux/pm.h> | 28 | #include <linux/pm.h> |
29 | #include <linux/clk.h> | ||
29 | 30 | ||
30 | #include "mcam-core.h" | 31 | #include "mcam-core.h" |
31 | 32 | ||
@@ -33,11 +34,14 @@ MODULE_ALIAS("platform:mmp-camera"); | |||
33 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | 34 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); |
34 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
35 | 36 | ||
37 | static char *mcam_clks[] = {"CCICAXICLK", "CCICFUNCLK", "CCICPHYCLK"}; | ||
38 | |||
36 | struct mmp_camera { | 39 | struct mmp_camera { |
37 | void *power_regs; | 40 | void *power_regs; |
38 | struct platform_device *pdev; | 41 | struct platform_device *pdev; |
39 | struct mcam_camera mcam; | 42 | struct mcam_camera mcam; |
40 | struct list_head devlist; | 43 | struct list_head devlist; |
44 | struct clk *mipi_clk; | ||
41 | int irq; | 45 | int irq; |
42 | }; | 46 | }; |
43 | 47 | ||
@@ -101,6 +105,27 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev) | |||
101 | #define CPU_SUBSYS_PMU_BASE 0xd4282800 | 105 | #define CPU_SUBSYS_PMU_BASE 0xd4282800 |
102 | #define REG_CCIC_DCGCR 0x28 /* CCIC dyn clock gate ctrl reg */ | 106 | #define REG_CCIC_DCGCR 0x28 /* CCIC dyn clock gate ctrl reg */ |
103 | #define REG_CCIC_CRCR 0x50 /* CCIC clk reset ctrl reg */ | 107 | #define REG_CCIC_CRCR 0x50 /* CCIC clk reset ctrl reg */ |
108 | #define REG_CCIC2_CRCR 0xf4 /* CCIC2 clk reset ctrl reg */ | ||
109 | |||
110 | static void mcam_clk_enable(struct mcam_camera *mcam) | ||
111 | { | ||
112 | unsigned int i; | ||
113 | |||
114 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
115 | if (!IS_ERR(mcam->clk[i])) | ||
116 | clk_prepare_enable(mcam->clk[i]); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static void mcam_clk_disable(struct mcam_camera *mcam) | ||
121 | { | ||
122 | int i; | ||
123 | |||
124 | for (i = NR_MCAM_CLK - 1; i >= 0; i--) { | ||
125 | if (!IS_ERR(mcam->clk[i])) | ||
126 | clk_disable_unprepare(mcam->clk[i]); | ||
127 | } | ||
128 | } | ||
104 | 129 | ||
105 | /* | 130 | /* |
106 | * Power control. | 131 | * Power control. |
@@ -112,10 +137,17 @@ static void mmpcam_power_up_ctlr(struct mmp_camera *cam) | |||
112 | mdelay(1); | 137 | mdelay(1); |
113 | } | 138 | } |
114 | 139 | ||
115 | static void mmpcam_power_up(struct mcam_camera *mcam) | 140 | static int mmpcam_power_up(struct mcam_camera *mcam) |
116 | { | 141 | { |
117 | struct mmp_camera *cam = mcam_to_cam(mcam); | 142 | struct mmp_camera *cam = mcam_to_cam(mcam); |
118 | struct mmp_camera_platform_data *pdata; | 143 | struct mmp_camera_platform_data *pdata; |
144 | |||
145 | if (mcam->bus_type == V4L2_MBUS_CSI2) { | ||
146 | cam->mipi_clk = devm_clk_get(mcam->dev, "mipi"); | ||
147 | if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0)) | ||
148 | return PTR_ERR(cam->mipi_clk); | ||
149 | } | ||
150 | |||
119 | /* | 151 | /* |
120 | * Turn on power and clocks to the controller. | 152 | * Turn on power and clocks to the controller. |
121 | */ | 153 | */ |
@@ -132,6 +164,10 @@ static void mmpcam_power_up(struct mcam_camera *mcam) | |||
132 | mdelay(5); | 164 | mdelay(5); |
133 | gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */ | 165 | gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */ |
134 | mdelay(5); | 166 | mdelay(5); |
167 | |||
168 | mcam_clk_enable(mcam); | ||
169 | |||
170 | return 0; | ||
135 | } | 171 | } |
136 | 172 | ||
137 | static void mmpcam_power_down(struct mcam_camera *mcam) | 173 | static void mmpcam_power_down(struct mcam_camera *mcam) |
@@ -149,8 +185,133 @@ static void mmpcam_power_down(struct mcam_camera *mcam) | |||
149 | pdata = cam->pdev->dev.platform_data; | 185 | pdata = cam->pdev->dev.platform_data; |
150 | gpio_set_value(pdata->sensor_power_gpio, 0); | 186 | gpio_set_value(pdata->sensor_power_gpio, 0); |
151 | gpio_set_value(pdata->sensor_reset_gpio, 0); | 187 | gpio_set_value(pdata->sensor_reset_gpio, 0); |
188 | |||
189 | if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) { | ||
190 | if (cam->mipi_clk) | ||
191 | devm_clk_put(mcam->dev, cam->mipi_clk); | ||
192 | cam->mipi_clk = NULL; | ||
193 | } | ||
194 | |||
195 | mcam_clk_disable(mcam); | ||
152 | } | 196 | } |
153 | 197 | ||
198 | void mcam_ctlr_reset(struct mcam_camera *mcam) | ||
199 | { | ||
200 | unsigned long val; | ||
201 | struct mmp_camera *cam = mcam_to_cam(mcam); | ||
202 | |||
203 | if (mcam->ccic_id) { | ||
204 | /* | ||
205 | * Using CCIC2 | ||
206 | */ | ||
207 | val = ioread32(cam->power_regs + REG_CCIC2_CRCR); | ||
208 | iowrite32(val & ~0x2, cam->power_regs + REG_CCIC2_CRCR); | ||
209 | iowrite32(val | 0x2, cam->power_regs + REG_CCIC2_CRCR); | ||
210 | } else { | ||
211 | /* | ||
212 | * Using CCIC1 | ||
213 | */ | ||
214 | val = ioread32(cam->power_regs + REG_CCIC_CRCR); | ||
215 | iowrite32(val & ~0x2, cam->power_regs + REG_CCIC_CRCR); | ||
216 | iowrite32(val | 0x2, cam->power_regs + REG_CCIC_CRCR); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * calc the dphy register values | ||
222 | * There are three dphy registers being used. | ||
223 | * dphy[0] - CSI2_DPHY3 | ||
224 | * dphy[1] - CSI2_DPHY5 | ||
225 | * dphy[2] - CSI2_DPHY6 | ||
226 | * CSI2_DPHY3 and CSI2_DPHY6 can be set with a default value | ||
227 | * or be calculated dynamically | ||
228 | */ | ||
229 | void mmpcam_calc_dphy(struct mcam_camera *mcam) | ||
230 | { | ||
231 | struct mmp_camera *cam = mcam_to_cam(mcam); | ||
232 | struct mmp_camera_platform_data *pdata = cam->pdev->dev.platform_data; | ||
233 | struct device *dev = &cam->pdev->dev; | ||
234 | unsigned long tx_clk_esc; | ||
235 | |||
236 | /* | ||
237 | * If CSI2_DPHY3 is calculated dynamically, | ||
238 | * pdata->lane_clk should be already set | ||
239 | * either in the board driver statically | ||
240 | * or in the sensor driver dynamically. | ||
241 | */ | ||
242 | /* | ||
243 | * dphy[0] - CSI2_DPHY3: | ||
244 | * bit 0 ~ bit 7: HS Term Enable. | ||
245 | * defines the time that the DPHY | ||
246 | * wait before enabling the data | ||
247 | * lane termination after detecting | ||
248 | * that the sensor has driven the data | ||
249 | * lanes to the LP00 bridge state. | ||
250 | * The value is calculated by: | ||
251 | * (Max T(D_TERM_EN)/Period(DDR)) - 1 | ||
252 | * bit 8 ~ bit 15: HS_SETTLE | ||
253 | * Time interval during which the HS | ||
254 | * receiver shall ignore any Data Lane | ||
255 | * HS transistions. | ||
256 | * The vaule has been calibrated on | ||
257 | * different boards. It seems to work well. | ||
258 | * | ||
259 | * More detail please refer | ||
260 | * MIPI Alliance Spectification for D-PHY | ||
261 | * document for explanation of HS-SETTLE | ||
262 | * and D-TERM-EN. | ||
263 | */ | ||
264 | switch (pdata->dphy3_algo) { | ||
265 | case DPHY3_ALGO_PXA910: | ||
266 | /* | ||
267 | * Calculate CSI2_DPHY3 algo for PXA910 | ||
268 | */ | ||
269 | pdata->dphy[0] = | ||
270 | (((1 + (pdata->lane_clk * 80) / 1000) & 0xff) << 8) | ||
271 | | (1 + pdata->lane_clk * 35 / 1000); | ||
272 | break; | ||
273 | case DPHY3_ALGO_PXA2128: | ||
274 | /* | ||
275 | * Calculate CSI2_DPHY3 algo for PXA2128 | ||
276 | */ | ||
277 | pdata->dphy[0] = | ||
278 | (((2 + (pdata->lane_clk * 110) / 1000) & 0xff) << 8) | ||
279 | | (1 + pdata->lane_clk * 35 / 1000); | ||
280 | break; | ||
281 | default: | ||
282 | /* | ||
283 | * Use default CSI2_DPHY3 value for PXA688/PXA988 | ||
284 | */ | ||
285 | dev_dbg(dev, "camera: use the default CSI2_DPHY3 value\n"); | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * mipi_clk will never be changed, it is a fixed value on MMP | ||
290 | */ | ||
291 | if (IS_ERR(cam->mipi_clk)) | ||
292 | return; | ||
293 | |||
294 | /* get the escape clk, this is hard coded */ | ||
295 | tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12; | ||
296 | |||
297 | /* | ||
298 | * dphy[2] - CSI2_DPHY6: | ||
299 | * bit 0 ~ bit 7: CK Term Enable | ||
300 | * Time for the Clock Lane receiver to enable the HS line | ||
301 | * termination. The value is calculated similarly with | ||
302 | * HS Term Enable | ||
303 | * bit 8 ~ bit 15: CK Settle | ||
304 | * Time interval during which the HS receiver shall ignore | ||
305 | * any Clock Lane HS transitions. | ||
306 | * The value is calibrated on the boards. | ||
307 | */ | ||
308 | pdata->dphy[2] = | ||
309 | ((((534 * tx_clk_esc) / 2000 - 1) & 0xff) << 8) | ||
310 | | (((38 * tx_clk_esc) / 1000 - 1) & 0xff); | ||
311 | |||
312 | dev_dbg(dev, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n", | ||
313 | pdata->dphy[0], pdata->dphy[1], pdata->dphy[2]); | ||
314 | } | ||
154 | 315 | ||
155 | static irqreturn_t mmpcam_irq(int irq, void *data) | 316 | static irqreturn_t mmpcam_irq(int irq, void *data) |
156 | { | 317 | { |
@@ -164,6 +325,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data) | |||
164 | return IRQ_RETVAL(handled); | 325 | return IRQ_RETVAL(handled); |
165 | } | 326 | } |
166 | 327 | ||
328 | static void mcam_deinit_clk(struct mcam_camera *mcam) | ||
329 | { | ||
330 | unsigned int i; | ||
331 | |||
332 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
333 | if (!IS_ERR(mcam->clk[i])) { | ||
334 | if (mcam->clk[i]) | ||
335 | devm_clk_put(mcam->dev, mcam->clk[i]); | ||
336 | } | ||
337 | mcam->clk[i] = NULL; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | static void mcam_init_clk(struct mcam_camera *mcam) | ||
342 | { | ||
343 | unsigned int i; | ||
344 | |||
345 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
346 | if (mcam_clks[i] != NULL) { | ||
347 | /* Some clks are not necessary on some boards | ||
348 | * We still try to run even it fails getting clk | ||
349 | */ | ||
350 | mcam->clk[i] = devm_clk_get(mcam->dev, mcam_clks[i]); | ||
351 | if (IS_ERR(mcam->clk[i])) | ||
352 | dev_warn(mcam->dev, "Could not get clk: %s\n", | ||
353 | mcam_clks[i]); | ||
354 | } | ||
355 | } | ||
356 | } | ||
167 | 357 | ||
168 | static int mmpcam_probe(struct platform_device *pdev) | 358 | static int mmpcam_probe(struct platform_device *pdev) |
169 | { | 359 | { |
@@ -173,17 +363,32 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
173 | struct mmp_camera_platform_data *pdata; | 363 | struct mmp_camera_platform_data *pdata; |
174 | int ret; | 364 | int ret; |
175 | 365 | ||
176 | cam = kzalloc(sizeof(*cam), GFP_KERNEL); | 366 | pdata = pdev->dev.platform_data; |
367 | if (!pdata) | ||
368 | return -ENODEV; | ||
369 | |||
370 | cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL); | ||
177 | if (cam == NULL) | 371 | if (cam == NULL) |
178 | return -ENOMEM; | 372 | return -ENOMEM; |
179 | cam->pdev = pdev; | 373 | cam->pdev = pdev; |
374 | cam->mipi_clk = NULL; | ||
180 | INIT_LIST_HEAD(&cam->devlist); | 375 | INIT_LIST_HEAD(&cam->devlist); |
181 | 376 | ||
182 | mcam = &cam->mcam; | 377 | mcam = &cam->mcam; |
183 | mcam->plat_power_up = mmpcam_power_up; | 378 | mcam->plat_power_up = mmpcam_power_up; |
184 | mcam->plat_power_down = mmpcam_power_down; | 379 | mcam->plat_power_down = mmpcam_power_down; |
380 | mcam->ctlr_reset = mcam_ctlr_reset; | ||
381 | mcam->calc_dphy = mmpcam_calc_dphy; | ||
185 | mcam->dev = &pdev->dev; | 382 | mcam->dev = &pdev->dev; |
186 | mcam->use_smbus = 0; | 383 | mcam->use_smbus = 0; |
384 | mcam->ccic_id = pdev->id; | ||
385 | mcam->mclk_min = pdata->mclk_min; | ||
386 | mcam->mclk_src = pdata->mclk_src; | ||
387 | mcam->mclk_div = pdata->mclk_div; | ||
388 | mcam->bus_type = pdata->bus_type; | ||
389 | mcam->dphy = pdata->dphy; | ||
390 | mcam->mipi_enabled = false; | ||
391 | mcam->lane = pdata->lane; | ||
187 | mcam->chip_id = MCAM_ARMADA610; | 392 | mcam->chip_id = MCAM_ARMADA610; |
188 | mcam->buffer_mode = B_DMA_sg; | 393 | mcam->buffer_mode = B_DMA_sg; |
189 | spin_lock_init(&mcam->dev_lock); | 394 | spin_lock_init(&mcam->dev_lock); |
@@ -191,69 +396,58 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
191 | * Get our I/O memory. | 396 | * Get our I/O memory. |
192 | */ | 397 | */ |
193 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 398 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
194 | if (res == NULL) { | 399 | mcam->regs = devm_ioremap_resource(&pdev->dev, res); |
195 | dev_err(&pdev->dev, "no iomem resource!\n"); | 400 | if (IS_ERR(mcam->regs)) |
196 | ret = -ENODEV; | 401 | return PTR_ERR(mcam->regs); |
197 | goto out_free; | ||
198 | } | ||
199 | mcam->regs = ioremap(res->start, resource_size(res)); | ||
200 | if (mcam->regs == NULL) { | ||
201 | dev_err(&pdev->dev, "MMIO ioremap fail\n"); | ||
202 | ret = -ENODEV; | ||
203 | goto out_free; | ||
204 | } | ||
205 | mcam->regs_size = resource_size(res); | 402 | mcam->regs_size = resource_size(res); |
206 | /* | 403 | /* |
207 | * Power/clock memory is elsewhere; get it too. Perhaps this | 404 | * Power/clock memory is elsewhere; get it too. Perhaps this |
208 | * should really be managed outside of this driver? | 405 | * should really be managed outside of this driver? |
209 | */ | 406 | */ |
210 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 407 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
211 | if (res == NULL) { | 408 | cam->power_regs = devm_ioremap_resource(&pdev->dev, res); |
212 | dev_err(&pdev->dev, "no power resource!\n"); | 409 | if (IS_ERR(cam->power_regs)) |
213 | ret = -ENODEV; | 410 | return PTR_ERR(cam->power_regs); |
214 | goto out_unmap1; | ||
215 | } | ||
216 | cam->power_regs = ioremap(res->start, resource_size(res)); | ||
217 | if (cam->power_regs == NULL) { | ||
218 | dev_err(&pdev->dev, "power MMIO ioremap fail\n"); | ||
219 | ret = -ENODEV; | ||
220 | goto out_unmap1; | ||
221 | } | ||
222 | /* | 411 | /* |
223 | * Find the i2c adapter. This assumes, of course, that the | 412 | * Find the i2c adapter. This assumes, of course, that the |
224 | * i2c bus is already up and functioning. | 413 | * i2c bus is already up and functioning. |
225 | */ | 414 | */ |
226 | pdata = pdev->dev.platform_data; | ||
227 | mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device); | 415 | mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device); |
228 | if (mcam->i2c_adapter == NULL) { | 416 | if (mcam->i2c_adapter == NULL) { |
229 | ret = -ENODEV; | ||
230 | dev_err(&pdev->dev, "No i2c adapter\n"); | 417 | dev_err(&pdev->dev, "No i2c adapter\n"); |
231 | goto out_unmap2; | 418 | return -ENODEV; |
232 | } | 419 | } |
233 | /* | 420 | /* |
234 | * Sensor GPIO pins. | 421 | * Sensor GPIO pins. |
235 | */ | 422 | */ |
236 | ret = gpio_request(pdata->sensor_power_gpio, "cam-power"); | 423 | ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio, |
424 | "cam-power"); | ||
237 | if (ret) { | 425 | if (ret) { |
238 | dev_err(&pdev->dev, "Can't get sensor power gpio %d", | 426 | dev_err(&pdev->dev, "Can't get sensor power gpio %d", |
239 | pdata->sensor_power_gpio); | 427 | pdata->sensor_power_gpio); |
240 | goto out_unmap2; | 428 | return ret; |
241 | } | 429 | } |
242 | gpio_direction_output(pdata->sensor_power_gpio, 0); | 430 | gpio_direction_output(pdata->sensor_power_gpio, 0); |
243 | ret = gpio_request(pdata->sensor_reset_gpio, "cam-reset"); | 431 | ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio, |
432 | "cam-reset"); | ||
244 | if (ret) { | 433 | if (ret) { |
245 | dev_err(&pdev->dev, "Can't get sensor reset gpio %d", | 434 | dev_err(&pdev->dev, "Can't get sensor reset gpio %d", |
246 | pdata->sensor_reset_gpio); | 435 | pdata->sensor_reset_gpio); |
247 | goto out_gpio; | 436 | return ret; |
248 | } | 437 | } |
249 | gpio_direction_output(pdata->sensor_reset_gpio, 0); | 438 | gpio_direction_output(pdata->sensor_reset_gpio, 0); |
439 | |||
440 | mcam_init_clk(mcam); | ||
441 | |||
250 | /* | 442 | /* |
251 | * Power the device up and hand it off to the core. | 443 | * Power the device up and hand it off to the core. |
252 | */ | 444 | */ |
253 | mmpcam_power_up(mcam); | 445 | ret = mmpcam_power_up(mcam); |
446 | if (ret) | ||
447 | goto out_deinit_clk; | ||
254 | ret = mccic_register(mcam); | 448 | ret = mccic_register(mcam); |
255 | if (ret) | 449 | if (ret) |
256 | goto out_gpio2; | 450 | goto out_power_down; |
257 | /* | 451 | /* |
258 | * Finally, set up our IRQ now that the core is ready to | 452 | * Finally, set up our IRQ now that the core is ready to |
259 | * deal with it. | 453 | * deal with it. |
@@ -264,8 +458,8 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
264 | goto out_unregister; | 458 | goto out_unregister; |
265 | } | 459 | } |
266 | cam->irq = res->start; | 460 | cam->irq = res->start; |
267 | ret = request_irq(cam->irq, mmpcam_irq, IRQF_SHARED, | 461 | ret = devm_request_irq(&pdev->dev, cam->irq, mmpcam_irq, IRQF_SHARED, |
268 | "mmp-camera", mcam); | 462 | "mmp-camera", mcam); |
269 | if (ret == 0) { | 463 | if (ret == 0) { |
270 | mmpcam_add_device(cam); | 464 | mmpcam_add_device(cam); |
271 | return 0; | 465 | return 0; |
@@ -273,17 +467,10 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
273 | 467 | ||
274 | out_unregister: | 468 | out_unregister: |
275 | mccic_shutdown(mcam); | 469 | mccic_shutdown(mcam); |
276 | out_gpio2: | 470 | out_power_down: |
277 | mmpcam_power_down(mcam); | 471 | mmpcam_power_down(mcam); |
278 | gpio_free(pdata->sensor_reset_gpio); | 472 | out_deinit_clk: |
279 | out_gpio: | 473 | mcam_deinit_clk(mcam); |
280 | gpio_free(pdata->sensor_power_gpio); | ||
281 | out_unmap2: | ||
282 | iounmap(cam->power_regs); | ||
283 | out_unmap1: | ||
284 | iounmap(mcam->regs); | ||
285 | out_free: | ||
286 | kfree(cam); | ||
287 | return ret; | 474 | return ret; |
288 | } | 475 | } |
289 | 476 | ||
@@ -300,6 +487,7 @@ static int mmpcam_remove(struct mmp_camera *cam) | |||
300 | pdata = cam->pdev->dev.platform_data; | 487 | pdata = cam->pdev->dev.platform_data; |
301 | gpio_free(pdata->sensor_reset_gpio); | 488 | gpio_free(pdata->sensor_reset_gpio); |
302 | gpio_free(pdata->sensor_power_gpio); | 489 | gpio_free(pdata->sensor_power_gpio); |
490 | mcam_deinit_clk(mcam); | ||
303 | iounmap(cam->power_regs); | 491 | iounmap(cam->power_regs); |
304 | iounmap(mcam->regs); | 492 | iounmap(mcam->regs); |
305 | kfree(cam); | 493 | kfree(cam); |
diff --git a/drivers/media/platform/s3c-camif/camif-regs.c b/drivers/media/platform/s3c-camif/camif-regs.c index a9e3b16460b8..ebf5b184cce4 100644 --- a/drivers/media/platform/s3c-camif/camif-regs.c +++ b/drivers/media/platform/s3c-camif/camif-regs.c | |||
@@ -106,15 +106,15 @@ static const u32 src_pixfmt_map[8][2] = { | |||
106 | void camif_hw_set_source_format(struct camif_dev *camif) | 106 | void camif_hw_set_source_format(struct camif_dev *camif) |
107 | { | 107 | { |
108 | struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt; | 108 | struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt; |
109 | unsigned int i = ARRAY_SIZE(src_pixfmt_map); | 109 | int i; |
110 | u32 cfg; | 110 | u32 cfg; |
111 | 111 | ||
112 | while (i-- >= 0) { | 112 | for (i = ARRAY_SIZE(src_pixfmt_map) - 1; i >= 0; i--) { |
113 | if (src_pixfmt_map[i][0] == mf->code) | 113 | if (src_pixfmt_map[i][0] == mf->code) |
114 | break; | 114 | break; |
115 | } | 115 | } |
116 | 116 | if (i < 0) { | |
117 | if (i == 0 && src_pixfmt_map[i][0] != mf->code) { | 117 | i = 0; |
118 | dev_err(camif->dev, | 118 | dev_err(camif->dev, |
119 | "Unsupported pixel code, falling back to %#08x\n", | 119 | "Unsupported pixel code, falling back to %#08x\n", |
120 | src_pixfmt_map[i][0]); | 120 | src_pixfmt_map[i][0]); |
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h index 363a97cc7681..2398cdf61341 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h | |||
@@ -374,9 +374,9 @@ | |||
374 | #define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16 | 374 | #define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16 |
375 | 375 | ||
376 | /* Buffer size requirements defined by hardware */ | 376 | /* Buffer size requirements defined by hardware */ |
377 | #define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 1) * 8) | 377 | #define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 3) * 8) |
378 | #define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \ | 378 | #define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \ |
379 | ((DIV_ROUND_UP(imw, 64) * DIV_ROUND_UP(imh, 64) * 256) + \ | 379 | (((((imw + 127) / 64) * 16) * DIV_ROUND_UP(imh, 64) * 256) + \ |
380 | (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) | 380 | (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) |
381 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64) | 381 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64) |
382 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \ | 382 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \ |
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h new file mode 100644 index 000000000000..ea5ec2a711af --- /dev/null +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Register definition file for Samsung MFC V7.x Interface (FIMV) driver | ||
3 | * | ||
4 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _REGS_MFC_V7_H | ||
13 | #define _REGS_MFC_V7_H | ||
14 | |||
15 | #include "regs-mfc-v6.h" | ||
16 | |||
17 | /* Additional features of v7 */ | ||
18 | #define S5P_FIMV_CODEC_VP8_ENC_V7 25 | ||
19 | |||
20 | /* Additional registers for v7 */ | ||
21 | #define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7 0xf47c | ||
22 | |||
23 | #define S5P_FIMV_E_SOURCE_FIRST_ADDR_V7 0xf9e0 | ||
24 | #define S5P_FIMV_E_SOURCE_SECOND_ADDR_V7 0xf9e4 | ||
25 | #define S5P_FIMV_E_SOURCE_THIRD_ADDR_V7 0xf9e8 | ||
26 | #define S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7 0xf9ec | ||
27 | #define S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7 0xf9f0 | ||
28 | #define S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7 0xf9f4 | ||
29 | |||
30 | #define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7 0xfa70 | ||
31 | #define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7 0xfa74 | ||
32 | |||
33 | #define S5P_FIMV_E_VP8_OPTIONS_V7 0xfdb0 | ||
34 | #define S5P_FIMV_E_VP8_FILTER_OPTIONS_V7 0xfdb4 | ||
35 | #define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION_V7 0xfdb8 | ||
36 | #define S5P_FIMV_E_VP8_NUM_T_LAYER_V7 0xfdc4 | ||
37 | |||
38 | /* MFCv7 variant defines */ | ||
39 | #define MAX_FW_SIZE_V7 (SZ_1M) /* 1MB */ | ||
40 | #define MAX_CPB_SIZE_V7 (3 * SZ_1M) /* 3MB */ | ||
41 | #define MFC_VERSION_V7 0x72 | ||
42 | #define MFC_NUM_PORTS_V7 1 | ||
43 | |||
44 | #define MFC_LUMA_PAD_BYTES_V7 256 | ||
45 | #define MFC_CHROMA_PAD_BYTES_V7 128 | ||
46 | |||
47 | /* MFCv7 Context buffer sizes */ | ||
48 | #define MFC_CTX_BUF_SIZE_V7 (30 * SZ_1K) /* 30KB */ | ||
49 | #define MFC_H264_DEC_CTX_BUF_SIZE_V7 (2 * SZ_1M) /* 2MB */ | ||
50 | #define MFC_OTHER_DEC_CTX_BUF_SIZE_V7 (20 * SZ_1K) /* 20KB */ | ||
51 | #define MFC_H264_ENC_CTX_BUF_SIZE_V7 (100 * SZ_1K) /* 100KB */ | ||
52 | #define MFC_OTHER_ENC_CTX_BUF_SIZE_V7 (10 * SZ_1K) /* 10KB */ | ||
53 | |||
54 | /* Buffer size defines */ | ||
55 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(w, h) \ | ||
56 | (SZ_1M + ((w) * 144) + (8192 * (h)) + 49216) | ||
57 | |||
58 | #define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(w, h) \ | ||
59 | (((w) * 48) + (((w) + 1) / 2 * 128) + 144 + 8192) | ||
60 | |||
61 | #endif /*_REGS_MFC_V7_H*/ | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index a130dcdb7206..084263dd126f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -1391,6 +1391,32 @@ static struct s5p_mfc_variant mfc_drvdata_v6 = { | |||
1391 | .fw_name = "s5p-mfc-v6.fw", | 1391 | .fw_name = "s5p-mfc-v6.fw", |
1392 | }; | 1392 | }; |
1393 | 1393 | ||
1394 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = { | ||
1395 | .dev_ctx = MFC_CTX_BUF_SIZE_V7, | ||
1396 | .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V7, | ||
1397 | .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V7, | ||
1398 | .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V7, | ||
1399 | .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V7, | ||
1400 | }; | ||
1401 | |||
1402 | struct s5p_mfc_buf_size buf_size_v7 = { | ||
1403 | .fw = MAX_FW_SIZE_V7, | ||
1404 | .cpb = MAX_CPB_SIZE_V7, | ||
1405 | .priv = &mfc_buf_size_v7, | ||
1406 | }; | ||
1407 | |||
1408 | struct s5p_mfc_buf_align mfc_buf_align_v7 = { | ||
1409 | .base = 0, | ||
1410 | }; | ||
1411 | |||
1412 | static struct s5p_mfc_variant mfc_drvdata_v7 = { | ||
1413 | .version = MFC_VERSION_V7, | ||
1414 | .port_num = MFC_NUM_PORTS_V7, | ||
1415 | .buf_size = &buf_size_v7, | ||
1416 | .buf_align = &mfc_buf_align_v7, | ||
1417 | .fw_name = "s5p-mfc-v7.fw", | ||
1418 | }; | ||
1419 | |||
1394 | static struct platform_device_id mfc_driver_ids[] = { | 1420 | static struct platform_device_id mfc_driver_ids[] = { |
1395 | { | 1421 | { |
1396 | .name = "s5p-mfc", | 1422 | .name = "s5p-mfc", |
@@ -1401,6 +1427,9 @@ static struct platform_device_id mfc_driver_ids[] = { | |||
1401 | }, { | 1427 | }, { |
1402 | .name = "s5p-mfc-v6", | 1428 | .name = "s5p-mfc-v6", |
1403 | .driver_data = (unsigned long)&mfc_drvdata_v6, | 1429 | .driver_data = (unsigned long)&mfc_drvdata_v6, |
1430 | }, { | ||
1431 | .name = "s5p-mfc-v7", | ||
1432 | .driver_data = (unsigned long)&mfc_drvdata_v7, | ||
1404 | }, | 1433 | }, |
1405 | {}, | 1434 | {}, |
1406 | }; | 1435 | }; |
@@ -1413,6 +1442,9 @@ static const struct of_device_id exynos_mfc_match[] = { | |||
1413 | }, { | 1442 | }, { |
1414 | .compatible = "samsung,mfc-v6", | 1443 | .compatible = "samsung,mfc-v6", |
1415 | .data = &mfc_drvdata_v6, | 1444 | .data = &mfc_drvdata_v6, |
1445 | }, { | ||
1446 | .compatible = "samsung,mfc-v7", | ||
1447 | .data = &mfc_drvdata_v7, | ||
1416 | }, | 1448 | }, |
1417 | {}, | 1449 | {}, |
1418 | }; | 1450 | }; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c index f0a41c95df84..242c033cf8bb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | |||
@@ -20,7 +20,7 @@ static struct s5p_mfc_hw_cmds *s5p_mfc_cmds; | |||
20 | 20 | ||
21 | void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev) | 21 | void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev) |
22 | { | 22 | { |
23 | if (IS_MFCV6(dev)) | 23 | if (IS_MFCV6_PLUS(dev)) |
24 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6(); | 24 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6(); |
25 | else | 25 | else |
26 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5(); | 26 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5(); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c index 5708fc3d9b4d..db796c8e7874 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | |||
@@ -108,6 +108,9 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) | |||
108 | case S5P_MFC_CODEC_H263_ENC: | 108 | case S5P_MFC_CODEC_H263_ENC: |
109 | codec_type = S5P_FIMV_CODEC_H263_ENC_V6; | 109 | codec_type = S5P_FIMV_CODEC_H263_ENC_V6; |
110 | break; | 110 | break; |
111 | case S5P_MFC_CODEC_VP8_ENC: | ||
112 | codec_type = S5P_FIMV_CODEC_VP8_ENC_V7; | ||
113 | break; | ||
111 | default: | 114 | default: |
112 | codec_type = S5P_FIMV_CODEC_NONE_V6; | 115 | codec_type = S5P_FIMV_CODEC_NONE_V6; |
113 | }; | 116 | }; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index ef4074cd5316..6920b546181a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <media/videobuf2-core.h> | 24 | #include <media/videobuf2-core.h> |
25 | #include "regs-mfc.h" | 25 | #include "regs-mfc.h" |
26 | #include "regs-mfc-v6.h" | 26 | #include "regs-mfc-v6.h" |
27 | #include "regs-mfc-v7.h" | ||
27 | 28 | ||
28 | /* Definitions related to MFC memory */ | 29 | /* Definitions related to MFC memory */ |
29 | 30 | ||
@@ -64,7 +65,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) | |||
64 | #define MFC_ENC_CAP_PLANE_COUNT 1 | 65 | #define MFC_ENC_CAP_PLANE_COUNT 1 |
65 | #define MFC_ENC_OUT_PLANE_COUNT 2 | 66 | #define MFC_ENC_OUT_PLANE_COUNT 2 |
66 | #define STUFF_BYTE 4 | 67 | #define STUFF_BYTE 4 |
67 | #define MFC_MAX_CTRLS 70 | 68 | #define MFC_MAX_CTRLS 77 |
68 | 69 | ||
69 | #define S5P_MFC_CODEC_NONE -1 | 70 | #define S5P_MFC_CODEC_NONE -1 |
70 | #define S5P_MFC_CODEC_H264_DEC 0 | 71 | #define S5P_MFC_CODEC_H264_DEC 0 |
@@ -80,6 +81,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) | |||
80 | #define S5P_MFC_CODEC_H264_MVC_ENC 21 | 81 | #define S5P_MFC_CODEC_H264_MVC_ENC 21 |
81 | #define S5P_MFC_CODEC_MPEG4_ENC 22 | 82 | #define S5P_MFC_CODEC_MPEG4_ENC 22 |
82 | #define S5P_MFC_CODEC_H263_ENC 23 | 83 | #define S5P_MFC_CODEC_H263_ENC 23 |
84 | #define S5P_MFC_CODEC_VP8_ENC 24 | ||
83 | 85 | ||
84 | #define S5P_MFC_R2H_CMD_EMPTY 0 | 86 | #define S5P_MFC_R2H_CMD_EMPTY 0 |
85 | #define S5P_MFC_R2H_CMD_SYS_INIT_RET 1 | 87 | #define S5P_MFC_R2H_CMD_SYS_INIT_RET 1 |
@@ -408,6 +410,21 @@ struct s5p_mfc_mpeg4_enc_params { | |||
408 | }; | 410 | }; |
409 | 411 | ||
410 | /** | 412 | /** |
413 | * struct s5p_mfc_vp8_enc_params - encoding parameters for vp8 | ||
414 | */ | ||
415 | struct s5p_mfc_vp8_enc_params { | ||
416 | u8 imd_4x4; | ||
417 | enum v4l2_vp8_num_partitions num_partitions; | ||
418 | enum v4l2_vp8_num_ref_frames num_ref; | ||
419 | u8 filter_level; | ||
420 | u8 filter_sharpness; | ||
421 | u32 golden_frame_ref_period; | ||
422 | enum v4l2_vp8_golden_frame_sel golden_frame_sel; | ||
423 | u8 hier_layer; | ||
424 | u8 hier_layer_qp[3]; | ||
425 | }; | ||
426 | |||
427 | /** | ||
411 | * struct s5p_mfc_enc_params - general encoding parameters | 428 | * struct s5p_mfc_enc_params - general encoding parameters |
412 | */ | 429 | */ |
413 | struct s5p_mfc_enc_params { | 430 | struct s5p_mfc_enc_params { |
@@ -441,6 +458,7 @@ struct s5p_mfc_enc_params { | |||
441 | struct { | 458 | struct { |
442 | struct s5p_mfc_h264_enc_params h264; | 459 | struct s5p_mfc_h264_enc_params h264; |
443 | struct s5p_mfc_mpeg4_enc_params mpeg4; | 460 | struct s5p_mfc_mpeg4_enc_params mpeg4; |
461 | struct s5p_mfc_vp8_enc_params vp8; | ||
444 | } codec; | 462 | } codec; |
445 | 463 | ||
446 | }; | 464 | }; |
@@ -683,6 +701,7 @@ void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); | |||
683 | #define HAS_PORTNUM(dev) (dev ? (dev->variant ? \ | 701 | #define HAS_PORTNUM(dev) (dev ? (dev->variant ? \ |
684 | (dev->variant->port_num ? 1 : 0) : 0) : 0) | 702 | (dev->variant->port_num ? 1 : 0) : 0) : 0) |
685 | #define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0) | 703 | #define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0) |
686 | #define IS_MFCV6(dev) (dev->variant->version >= 0x60 ? 1 : 0) | 704 | #define IS_MFCV6_PLUS(dev) (dev->variant->version >= 0x60 ? 1 : 0) |
705 | #define IS_MFCV7(dev) (dev->variant->version >= 0x70 ? 1 : 0) | ||
687 | 706 | ||
688 | #endif /* S5P_MFC_COMMON_H_ */ | 707 | #endif /* S5P_MFC_COMMON_H_ */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index dc1fc94a488d..7cab6849fb5b 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | |||
@@ -164,7 +164,7 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) | |||
164 | 164 | ||
165 | mfc_debug_enter(); | 165 | mfc_debug_enter(); |
166 | 166 | ||
167 | if (IS_MFCV6(dev)) { | 167 | if (IS_MFCV6_PLUS(dev)) { |
168 | /* Reset IP */ | 168 | /* Reset IP */ |
169 | /* except RISC, reset */ | 169 | /* except RISC, reset */ |
170 | mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6); | 170 | mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6); |
@@ -213,7 +213,7 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) | |||
213 | 213 | ||
214 | static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) | 214 | static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) |
215 | { | 215 | { |
216 | if (IS_MFCV6(dev)) { | 216 | if (IS_MFCV6_PLUS(dev)) { |
217 | mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6); | 217 | mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6); |
218 | mfc_debug(2, "Base Address : %08x\n", dev->bank1); | 218 | mfc_debug(2, "Base Address : %08x\n", dev->bank1); |
219 | } else { | 219 | } else { |
@@ -226,7 +226,7 @@ static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) | |||
226 | 226 | ||
227 | static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev) | 227 | static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev) |
228 | { | 228 | { |
229 | if (IS_MFCV6(dev)) { | 229 | if (IS_MFCV6_PLUS(dev)) { |
230 | /* Zero initialization should be done before RESET. | 230 | /* Zero initialization should be done before RESET. |
231 | * Nothing to do here. */ | 231 | * Nothing to do here. */ |
232 | } else { | 232 | } else { |
@@ -264,7 +264,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
264 | s5p_mfc_clear_cmds(dev); | 264 | s5p_mfc_clear_cmds(dev); |
265 | /* 3. Release reset signal to the RISC */ | 265 | /* 3. Release reset signal to the RISC */ |
266 | s5p_mfc_clean_dev_int_flags(dev); | 266 | s5p_mfc_clean_dev_int_flags(dev); |
267 | if (IS_MFCV6(dev)) | 267 | if (IS_MFCV6_PLUS(dev)) |
268 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); | 268 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); |
269 | else | 269 | else |
270 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); | 270 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); |
@@ -301,7 +301,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
301 | s5p_mfc_clock_off(); | 301 | s5p_mfc_clock_off(); |
302 | return -EIO; | 302 | return -EIO; |
303 | } | 303 | } |
304 | if (IS_MFCV6(dev)) | 304 | if (IS_MFCV6_PLUS(dev)) |
305 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6); | 305 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6); |
306 | else | 306 | else |
307 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION); | 307 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION); |
@@ -380,7 +380,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) | |||
380 | return ret; | 380 | return ret; |
381 | } | 381 | } |
382 | /* 4. Release reset signal to the RISC */ | 382 | /* 4. Release reset signal to the RISC */ |
383 | if (IS_MFCV6(dev)) | 383 | if (IS_MFCV6_PLUS(dev)) |
384 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); | 384 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); |
385 | else | 385 | else |
386 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); | 386 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 4f6dd42c9adb..8faf9691712d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | |||
@@ -386,7 +386,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
386 | mfc_err("Unknown codec\n"); | 386 | mfc_err("Unknown codec\n"); |
387 | return -EINVAL; | 387 | return -EINVAL; |
388 | } | 388 | } |
389 | if (!IS_MFCV6(dev)) { | 389 | if (!IS_MFCV6_PLUS(dev)) { |
390 | if (fmt->fourcc == V4L2_PIX_FMT_VP8) { | 390 | if (fmt->fourcc == V4L2_PIX_FMT_VP8) { |
391 | mfc_err("Not supported format.\n"); | 391 | mfc_err("Not supported format.\n"); |
392 | return -EINVAL; | 392 | return -EINVAL; |
@@ -398,10 +398,11 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
398 | mfc_err("Unsupported format for destination.\n"); | 398 | mfc_err("Unsupported format for destination.\n"); |
399 | return -EINVAL; | 399 | return -EINVAL; |
400 | } | 400 | } |
401 | if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | 401 | if (IS_MFCV6_PLUS(dev) && |
402 | (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | ||
402 | mfc_err("Not supported format.\n"); | 403 | mfc_err("Not supported format.\n"); |
403 | return -EINVAL; | 404 | return -EINVAL; |
404 | } else if (!IS_MFCV6(dev) && | 405 | } else if (!IS_MFCV6_PLUS(dev) && |
405 | (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { | 406 | (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { |
406 | mfc_err("Not supported format.\n"); | 407 | mfc_err("Not supported format.\n"); |
407 | return -EINVAL; | 408 | return -EINVAL; |
@@ -925,7 +926,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
925 | psize[0] = ctx->luma_size; | 926 | psize[0] = ctx->luma_size; |
926 | psize[1] = ctx->chroma_size; | 927 | psize[1] = ctx->chroma_size; |
927 | 928 | ||
928 | if (IS_MFCV6(dev)) | 929 | if (IS_MFCV6_PLUS(dev)) |
929 | allocators[0] = | 930 | allocators[0] = |
930 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | 931 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; |
931 | else | 932 | else |
@@ -1050,7 +1051,7 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) | |||
1050 | ctx->dpb_flush_flag = 1; | 1051 | ctx->dpb_flush_flag = 1; |
1051 | ctx->dec_dst_flag = 0; | 1052 | ctx->dec_dst_flag = 0; |
1052 | spin_unlock_irqrestore(&dev->irqlock, flags); | 1053 | spin_unlock_irqrestore(&dev->irqlock, flags); |
1053 | if (IS_MFCV6(dev) && (ctx->state == MFCINST_RUNNING)) { | 1054 | if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) { |
1054 | ctx->state = MFCINST_FLUSH; | 1055 | ctx->state = MFCINST_FLUSH; |
1055 | set_work_bit_irqsave(ctx); | 1056 | set_work_bit_irqsave(ctx); |
1056 | s5p_mfc_clean_ctx_int_flags(ctx); | 1057 | s5p_mfc_clean_ctx_int_flags(ctx); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 59e56f4c8ce3..41f5a3c10dbd 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | |||
@@ -84,6 +84,13 @@ static struct s5p_mfc_fmt formats[] = { | |||
84 | .type = MFC_FMT_ENC, | 84 | .type = MFC_FMT_ENC, |
85 | .num_planes = 1, | 85 | .num_planes = 1, |
86 | }, | 86 | }, |
87 | { | ||
88 | .name = "VP8 Encoded Stream", | ||
89 | .fourcc = V4L2_PIX_FMT_VP8, | ||
90 | .codec_mode = S5P_MFC_CODEC_VP8_ENC, | ||
91 | .type = MFC_FMT_ENC, | ||
92 | .num_planes = 1, | ||
93 | }, | ||
87 | }; | 94 | }; |
88 | 95 | ||
89 | #define NUM_FORMATS ARRAY_SIZE(formats) | 96 | #define NUM_FORMATS ARRAY_SIZE(formats) |
@@ -557,6 +564,60 @@ static struct mfc_control controls[] = { | |||
557 | .step = 1, | 564 | .step = 1, |
558 | .default_value = 0, | 565 | .default_value = 0, |
559 | }, | 566 | }, |
567 | { | ||
568 | .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS, | ||
569 | .type = V4L2_CTRL_TYPE_INTEGER_MENU, | ||
570 | .maximum = V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS, | ||
571 | .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION, | ||
572 | .menu_skip_mask = 0, | ||
573 | }, | ||
574 | { | ||
575 | .id = V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4, | ||
576 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
577 | .minimum = 0, | ||
578 | .maximum = 1, | ||
579 | .step = 1, | ||
580 | .default_value = 0, | ||
581 | }, | ||
582 | { | ||
583 | .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES, | ||
584 | .type = V4L2_CTRL_TYPE_INTEGER_MENU, | ||
585 | .maximum = V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME, | ||
586 | .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME, | ||
587 | .menu_skip_mask = 0, | ||
588 | }, | ||
589 | { | ||
590 | .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL, | ||
591 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
592 | .minimum = 0, | ||
593 | .maximum = 63, | ||
594 | .step = 1, | ||
595 | .default_value = 0, | ||
596 | }, | ||
597 | { | ||
598 | .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS, | ||
599 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
600 | .minimum = 0, | ||
601 | .maximum = 7, | ||
602 | .step = 1, | ||
603 | .default_value = 0, | ||
604 | }, | ||
605 | { | ||
606 | .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD, | ||
607 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
608 | .minimum = 0, | ||
609 | .maximum = (1 << 16) - 1, | ||
610 | .step = 1, | ||
611 | .default_value = 0, | ||
612 | }, | ||
613 | { | ||
614 | .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL, | ||
615 | .type = V4L2_CTRL_TYPE_MENU, | ||
616 | .minimum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV, | ||
617 | .maximum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD, | ||
618 | .default_value = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV, | ||
619 | .menu_skip_mask = 0, | ||
620 | }, | ||
560 | }; | 621 | }; |
561 | 622 | ||
562 | #define NUM_CTRLS ARRAY_SIZE(controls) | 623 | #define NUM_CTRLS ARRAY_SIZE(controls) |
@@ -663,7 +724,7 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) | |||
663 | spin_unlock_irqrestore(&dev->irqlock, flags); | 724 | spin_unlock_irqrestore(&dev->irqlock, flags); |
664 | } | 725 | } |
665 | 726 | ||
666 | if (!IS_MFCV6(dev)) { | 727 | if (!IS_MFCV6_PLUS(dev)) { |
667 | ctx->state = MFCINST_RUNNING; | 728 | ctx->state = MFCINST_RUNNING; |
668 | if (s5p_mfc_ctx_ready(ctx)) | 729 | if (s5p_mfc_ctx_ready(ctx)) |
669 | set_work_bit_irqsave(ctx); | 730 | set_work_bit_irqsave(ctx); |
@@ -917,6 +978,11 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
917 | return -EINVAL; | 978 | return -EINVAL; |
918 | } | 979 | } |
919 | 980 | ||
981 | if (!IS_MFCV7(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { | ||
982 | mfc_err("VP8 is supported only in MFC v7\n"); | ||
983 | return -EINVAL; | ||
984 | } | ||
985 | |||
920 | if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { | 986 | if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { |
921 | mfc_err("must be set encoding output size\n"); | 987 | mfc_err("must be set encoding output size\n"); |
922 | return -EINVAL; | 988 | return -EINVAL; |
@@ -931,12 +997,12 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
931 | return -EINVAL; | 997 | return -EINVAL; |
932 | } | 998 | } |
933 | 999 | ||
934 | if (!IS_MFCV6(dev)) { | 1000 | if (!IS_MFCV6_PLUS(dev)) { |
935 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { | 1001 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { |
936 | mfc_err("Not supported format.\n"); | 1002 | mfc_err("Not supported format.\n"); |
937 | return -EINVAL; | 1003 | return -EINVAL; |
938 | } | 1004 | } |
939 | } else if (IS_MFCV6(dev)) { | 1005 | } else if (IS_MFCV6_PLUS(dev)) { |
940 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT) { | 1006 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT) { |
941 | mfc_err("Not supported format.\n"); | 1007 | mfc_err("Not supported format.\n"); |
942 | return -EINVAL; | 1008 | return -EINVAL; |
@@ -1060,7 +1126,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1060 | return -EINVAL; | 1126 | return -EINVAL; |
1061 | } | 1127 | } |
1062 | 1128 | ||
1063 | if (IS_MFCV6(dev)) { | 1129 | if (IS_MFCV6_PLUS(dev)) { |
1064 | /* Check for min encoder buffers */ | 1130 | /* Check for min encoder buffers */ |
1065 | if (ctx->pb_count && | 1131 | if (ctx->pb_count && |
1066 | (reqbufs->count < ctx->pb_count)) { | 1132 | (reqbufs->count < ctx->pb_count)) { |
@@ -1341,7 +1407,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
1341 | S5P_FIMV_ENC_PROFILE_H264_BASELINE; | 1407 | S5P_FIMV_ENC_PROFILE_H264_BASELINE; |
1342 | break; | 1408 | break; |
1343 | case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: | 1409 | case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: |
1344 | if (IS_MFCV6(dev)) | 1410 | if (IS_MFCV6_PLUS(dev)) |
1345 | p->codec.h264.profile = | 1411 | p->codec.h264.profile = |
1346 | S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE; | 1412 | S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE; |
1347 | else | 1413 | else |
@@ -1470,6 +1536,27 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
1470 | case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: | 1536 | case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: |
1471 | p->codec.mpeg4.quarter_pixel = ctrl->val; | 1537 | p->codec.mpeg4.quarter_pixel = ctrl->val; |
1472 | break; | 1538 | break; |
1539 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: | ||
1540 | p->codec.vp8.num_partitions = ctrl->val; | ||
1541 | break; | ||
1542 | case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4: | ||
1543 | p->codec.vp8.imd_4x4 = ctrl->val; | ||
1544 | break; | ||
1545 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: | ||
1546 | p->codec.vp8.num_ref = ctrl->val; | ||
1547 | break; | ||
1548 | case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL: | ||
1549 | p->codec.vp8.filter_level = ctrl->val; | ||
1550 | break; | ||
1551 | case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS: | ||
1552 | p->codec.vp8.filter_sharpness = ctrl->val; | ||
1553 | break; | ||
1554 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD: | ||
1555 | p->codec.vp8.golden_frame_ref_period = ctrl->val; | ||
1556 | break; | ||
1557 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: | ||
1558 | p->codec.vp8.golden_frame_sel = ctrl->val; | ||
1559 | break; | ||
1473 | default: | 1560 | default: |
1474 | v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n", | 1561 | v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n", |
1475 | ctrl->id, ctrl->val); | 1562 | ctrl->id, ctrl->val); |
@@ -1650,9 +1737,11 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
1650 | *buf_count = 1; | 1737 | *buf_count = 1; |
1651 | if (*buf_count > MFC_MAX_BUFFERS) | 1738 | if (*buf_count > MFC_MAX_BUFFERS) |
1652 | *buf_count = MFC_MAX_BUFFERS; | 1739 | *buf_count = MFC_MAX_BUFFERS; |
1740 | |||
1653 | psize[0] = ctx->luma_size; | 1741 | psize[0] = ctx->luma_size; |
1654 | psize[1] = ctx->chroma_size; | 1742 | psize[1] = ctx->chroma_size; |
1655 | if (IS_MFCV6(dev)) { | 1743 | |
1744 | if (IS_MFCV6_PLUS(dev)) { | ||
1656 | allocators[0] = | 1745 | allocators[0] = |
1657 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | 1746 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; |
1658 | allocators[1] = | 1747 | allocators[1] = |
@@ -1761,7 +1850,8 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1761 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | 1850 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); |
1762 | struct s5p_mfc_dev *dev = ctx->dev; | 1851 | struct s5p_mfc_dev *dev = ctx->dev; |
1763 | 1852 | ||
1764 | if (IS_MFCV6(dev) && (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) { | 1853 | if (IS_MFCV6_PLUS(dev) && |
1854 | (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) { | ||
1765 | 1855 | ||
1766 | if ((ctx->state == MFCINST_GOT_INST) && | 1856 | if ((ctx->state == MFCINST_GOT_INST) && |
1767 | (dev->curr_ctx == ctx->num) && dev->hw_lock) { | 1857 | (dev->curr_ctx == ctx->num) && dev->hw_lock) { |
@@ -1915,7 +2005,9 @@ int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx) | |||
1915 | ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler, | 2005 | ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler, |
1916 | &cfg, NULL); | 2006 | &cfg, NULL); |
1917 | } else { | 2007 | } else { |
1918 | if (controls[i].type == V4L2_CTRL_TYPE_MENU) { | 2008 | if ((controls[i].type == V4L2_CTRL_TYPE_MENU) || |
2009 | (controls[i].type == | ||
2010 | V4L2_CTRL_TYPE_INTEGER_MENU)) { | ||
1919 | ctx->ctrls[i] = v4l2_ctrl_new_std_menu( | 2011 | ctx->ctrls[i] = v4l2_ctrl_new_std_menu( |
1920 | &ctx->ctrl_handler, | 2012 | &ctx->ctrl_handler, |
1921 | &s5p_mfc_enc_ctrl_ops, controls[i].id, | 2013 | &s5p_mfc_enc_ctrl_ops, controls[i].id, |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 10f8ac37cecd..3c01c339d696 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | |||
@@ -21,7 +21,7 @@ static struct s5p_mfc_hw_ops *s5p_mfc_ops; | |||
21 | 21 | ||
22 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) | 22 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) |
23 | { | 23 | { |
24 | if (IS_MFCV6(dev)) { | 24 | if (IS_MFCV6_PLUS(dev)) { |
25 | s5p_mfc_ops = s5p_mfc_init_hw_ops_v6(); | 25 | s5p_mfc_ops = s5p_mfc_init_hw_ops_v6(); |
26 | dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6; | 26 | dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6; |
27 | } else { | 27 | } else { |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 66f0d042357f..461358c4a790 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | |||
@@ -80,6 +80,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
80 | ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * | 80 | ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * |
81 | ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height), | 81 | ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height), |
82 | S5P_FIMV_TMV_BUFFER_ALIGN_V6); | 82 | S5P_FIMV_TMV_BUFFER_ALIGN_V6); |
83 | |||
83 | ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * | 84 | ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * |
84 | S5P_FIMV_LUMA_MB_TO_PIXEL_V6, | 85 | S5P_FIMV_LUMA_MB_TO_PIXEL_V6, |
85 | S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6); | 86 | S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6); |
@@ -112,10 +113,18 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
112 | (ctx->mv_count * ctx->mv_size); | 113 | (ctx->mv_count * ctx->mv_size); |
113 | break; | 114 | break; |
114 | case S5P_MFC_CODEC_MPEG4_DEC: | 115 | case S5P_MFC_CODEC_MPEG4_DEC: |
115 | ctx->scratch_buf_size = | 116 | if (IS_MFCV7(dev)) { |
116 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6( | 117 | ctx->scratch_buf_size = |
117 | mb_width, | 118 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7( |
118 | mb_height); | 119 | mb_width, |
120 | mb_height); | ||
121 | } else { | ||
122 | ctx->scratch_buf_size = | ||
123 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6( | ||
124 | mb_width, | ||
125 | mb_height); | ||
126 | } | ||
127 | |||
119 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 128 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
120 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 129 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
121 | ctx->bank1.size = ctx->scratch_buf_size; | 130 | ctx->bank1.size = ctx->scratch_buf_size; |
@@ -179,6 +188,19 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
179 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | 188 | ctx->chroma_dpb_size + ctx->me_buffer_size)); |
180 | ctx->bank2.size = 0; | 189 | ctx->bank2.size = 0; |
181 | break; | 190 | break; |
191 | case S5P_MFC_CODEC_VP8_ENC: | ||
192 | ctx->scratch_buf_size = | ||
193 | S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7( | ||
194 | mb_width, | ||
195 | mb_height); | ||
196 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
197 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
198 | ctx->bank1.size = | ||
199 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | ||
200 | (ctx->pb_count * (ctx->luma_dpb_size + | ||
201 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | ||
202 | ctx->bank2.size = 0; | ||
203 | break; | ||
182 | default: | 204 | default: |
183 | break; | 205 | break; |
184 | } | 206 | } |
@@ -228,6 +250,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
228 | break; | 250 | break; |
229 | case S5P_MFC_CODEC_MPEG4_ENC: | 251 | case S5P_MFC_CODEC_MPEG4_ENC: |
230 | case S5P_MFC_CODEC_H263_ENC: | 252 | case S5P_MFC_CODEC_H263_ENC: |
253 | case S5P_MFC_CODEC_VP8_ENC: | ||
231 | ctx->ctx.size = buf_size->other_enc_ctx; | 254 | ctx->ctx.size = buf_size->other_enc_ctx; |
232 | break; | 255 | break; |
233 | default: | 256 | default: |
@@ -329,6 +352,12 @@ static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx) | |||
329 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6); | 352 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6); |
330 | ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256); | 353 | ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256); |
331 | ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256); | 354 | ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256); |
355 | |||
356 | /* MFCv7 needs pad bytes for Luma and Chroma */ | ||
357 | if (IS_MFCV7(ctx->dev)) { | ||
358 | ctx->luma_size += MFC_LUMA_PAD_BYTES_V7; | ||
359 | ctx->chroma_size += MFC_CHROMA_PAD_BYTES_V7; | ||
360 | } | ||
332 | } | 361 | } |
333 | 362 | ||
334 | /* Set registers for decoding stream buffer */ | 363 | /* Set registers for decoding stream buffer */ |
@@ -453,8 +482,13 @@ static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | |||
453 | { | 482 | { |
454 | struct s5p_mfc_dev *dev = ctx->dev; | 483 | struct s5p_mfc_dev *dev = ctx->dev; |
455 | 484 | ||
456 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */ | 485 | if (IS_MFCV7(dev)) { |
457 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | 486 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_FIRST_ADDR_V7); |
487 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_SECOND_ADDR_V7); | ||
488 | } else { | ||
489 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); | ||
490 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | ||
491 | } | ||
458 | 492 | ||
459 | mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr); | 493 | mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr); |
460 | mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr); | 494 | mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr); |
@@ -466,8 +500,13 @@ static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | |||
466 | struct s5p_mfc_dev *dev = ctx->dev; | 500 | struct s5p_mfc_dev *dev = ctx->dev; |
467 | unsigned long enc_recon_y_addr, enc_recon_c_addr; | 501 | unsigned long enc_recon_y_addr, enc_recon_c_addr; |
468 | 502 | ||
469 | *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); | 503 | if (IS_MFCV7(dev)) { |
470 | *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); | 504 | *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7); |
505 | *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7); | ||
506 | } else { | ||
507 | *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); | ||
508 | *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); | ||
509 | } | ||
471 | 510 | ||
472 | enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); | 511 | enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); |
473 | enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); | 512 | enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); |
@@ -1140,6 +1179,80 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) | |||
1140 | return 0; | 1179 | return 0; |
1141 | } | 1180 | } |
1142 | 1181 | ||
1182 | static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx) | ||
1183 | { | ||
1184 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1185 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
1186 | struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8; | ||
1187 | unsigned int reg = 0; | ||
1188 | unsigned int val = 0; | ||
1189 | |||
1190 | mfc_debug_enter(); | ||
1191 | |||
1192 | s5p_mfc_set_enc_params(ctx); | ||
1193 | |||
1194 | /* pictype : number of B */ | ||
1195 | reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); | ||
1196 | reg &= ~(0x3 << 16); | ||
1197 | reg |= ((p->num_b_frame & 0x3) << 16); | ||
1198 | WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | ||
1199 | |||
1200 | /* profile & level */ | ||
1201 | reg = 0; | ||
1202 | /** profile */ | ||
1203 | reg |= (0x1 << 4); | ||
1204 | WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | ||
1205 | |||
1206 | /* rate control config. */ | ||
1207 | reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | ||
1208 | /** macroblock level rate control */ | ||
1209 | reg &= ~(0x1 << 8); | ||
1210 | reg |= ((p->rc_mb & 0x1) << 8); | ||
1211 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
1212 | |||
1213 | /* frame rate */ | ||
1214 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | ||
1215 | reg = 0; | ||
1216 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | ||
1217 | reg |= p->rc_framerate_denom & 0xFFFF; | ||
1218 | WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | ||
1219 | } | ||
1220 | |||
1221 | /* vbv buffer size */ | ||
1222 | if (p->frame_skip_mode == | ||
1223 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
1224 | WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | ||
1225 | |||
1226 | if (p->rc_frame) | ||
1227 | WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | ||
1228 | } | ||
1229 | |||
1230 | /* VP8 specific params */ | ||
1231 | reg = 0; | ||
1232 | reg |= (p_vp8->imd_4x4 & 0x1) << 10; | ||
1233 | switch (p_vp8->num_partitions) { | ||
1234 | case V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION: | ||
1235 | val = 0; | ||
1236 | break; | ||
1237 | case V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS: | ||
1238 | val = 2; | ||
1239 | break; | ||
1240 | case V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS: | ||
1241 | val = 4; | ||
1242 | break; | ||
1243 | case V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS: | ||
1244 | val = 8; | ||
1245 | break; | ||
1246 | } | ||
1247 | reg |= (val & 0xF) << 3; | ||
1248 | reg |= (p_vp8->num_ref & 0x2); | ||
1249 | WRITEL(reg, S5P_FIMV_E_VP8_OPTIONS_V7); | ||
1250 | |||
1251 | mfc_debug_leave(); | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1143 | /* Initialize decoding */ | 1256 | /* Initialize decoding */ |
1144 | static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | 1257 | static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) |
1145 | { | 1258 | { |
@@ -1166,6 +1279,12 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
1166 | reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); | 1279 | reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); |
1167 | WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); | 1280 | WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); |
1168 | } | 1281 | } |
1282 | |||
1283 | if (IS_MFCV7(dev)) { | ||
1284 | WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | ||
1285 | reg = 0; | ||
1286 | } | ||
1287 | |||
1169 | /* Setup loop filter, for decoding this is only valid for MPEG4 */ | 1288 | /* Setup loop filter, for decoding this is only valid for MPEG4 */ |
1170 | if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) { | 1289 | if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) { |
1171 | mfc_debug(2, "Set loop filter to: %d\n", | 1290 | mfc_debug(2, "Set loop filter to: %d\n", |
@@ -1176,7 +1295,10 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
1176 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) | 1295 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) |
1177 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); | 1296 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); |
1178 | 1297 | ||
1179 | WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | 1298 | if (IS_MFCV7(dev)) |
1299 | WRITEL(reg, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7); | ||
1300 | else | ||
1301 | WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | ||
1180 | 1302 | ||
1181 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ | 1303 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
1182 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M) | 1304 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M) |
@@ -1184,6 +1306,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
1184 | else | 1306 | else |
1185 | WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); | 1307 | WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); |
1186 | 1308 | ||
1309 | |||
1187 | /* sei parse */ | 1310 | /* sei parse */ |
1188 | WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6); | 1311 | WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6); |
1189 | 1312 | ||
@@ -1248,12 +1371,20 @@ static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) | |||
1248 | s5p_mfc_set_enc_params_mpeg4(ctx); | 1371 | s5p_mfc_set_enc_params_mpeg4(ctx); |
1249 | else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC) | 1372 | else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC) |
1250 | s5p_mfc_set_enc_params_h263(ctx); | 1373 | s5p_mfc_set_enc_params_h263(ctx); |
1374 | else if (ctx->codec_mode == S5P_MFC_CODEC_VP8_ENC) | ||
1375 | s5p_mfc_set_enc_params_vp8(ctx); | ||
1251 | else { | 1376 | else { |
1252 | mfc_err("Unknown codec for encoding (%x).\n", | 1377 | mfc_err("Unknown codec for encoding (%x).\n", |
1253 | ctx->codec_mode); | 1378 | ctx->codec_mode); |
1254 | return -EINVAL; | 1379 | return -EINVAL; |
1255 | } | 1380 | } |
1256 | 1381 | ||
1382 | /* Set stride lengths */ | ||
1383 | if (IS_MFCV7(dev)) { | ||
1384 | WRITEL(ctx->img_width, S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7); | ||
1385 | WRITEL(ctx->img_width, S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7); | ||
1386 | } | ||
1387 | |||
1257 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | 1388 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); |
1258 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | 1389 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
1259 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); | 1390 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); |
diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 1b34c3629858..534722c04ec5 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
38 | #include <media/v4l2-dev.h> | 38 | #include <media/v4l2-dev.h> |
39 | #include <media/v4l2-device.h> | 39 | #include <media/v4l2-device.h> |
40 | #include <media/v4l2-dv-timings.h> | ||
40 | 41 | ||
41 | #include "regs-hdmi.h" | 42 | #include "regs-hdmi.h" |
42 | 43 | ||
@@ -625,7 +626,7 @@ static int hdmi_s_dv_timings(struct v4l2_subdev *sd, | |||
625 | int i; | 626 | int i; |
626 | 627 | ||
627 | for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++) | 628 | for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++) |
628 | if (v4l_match_dv_timings(&hdmi_timings[i].dv_timings, | 629 | if (v4l2_match_dv_timings(&hdmi_timings[i].dv_timings, |
629 | timings, 0)) | 630 | timings, 0)) |
630 | break; | 631 | break; |
631 | if (i == ARRAY_SIZE(hdmi_timings)) { | 632 | if (i == ARRAY_SIZE(hdmi_timings)) { |
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index 626dcccc37da..af39c4665554 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig | |||
@@ -44,6 +44,14 @@ config VIDEO_PXA27x | |||
44 | ---help--- | 44 | ---help--- |
45 | This is a v4l2 driver for the PXA27x Quick Capture Interface | 45 | This is a v4l2 driver for the PXA27x Quick Capture Interface |
46 | 46 | ||
47 | config VIDEO_RCAR_VIN | ||
48 | tristate "R-Car Video Input (VIN) support" | ||
49 | depends on VIDEO_DEV && SOC_CAMERA | ||
50 | select VIDEOBUF2_DMA_CONTIG | ||
51 | select SOC_CAMERA_SCALE_CROP | ||
52 | ---help--- | ||
53 | This is a v4l2 driver for the R-Car VIN Interface | ||
54 | |||
47 | config VIDEO_SH_MOBILE_CSI2 | 55 | config VIDEO_SH_MOBILE_CSI2 |
48 | tristate "SuperH Mobile MIPI CSI-2 Interface driver" | 56 | tristate "SuperH Mobile MIPI CSI-2 Interface driver" |
49 | depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK | 57 | depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK |
diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index 39186224c16a..8aed26d7a64d 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile | |||
@@ -14,3 +14,4 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o | |||
14 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o | 14 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o |
15 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | 15 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
16 | obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o | 16 | obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o |
17 | obj-$(CONFIG_VIDEO_RCAR_VIN) += rcar_vin.o | ||
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 1047e3e8db77..8f9f6211c52e 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c | |||
@@ -672,7 +672,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
672 | fmt = soc_mbus_get_fmtdesc(code); | 672 | fmt = soc_mbus_get_fmtdesc(code); |
673 | if (!fmt) { | 673 | if (!fmt) { |
674 | dev_warn(icd->parent, | 674 | dev_warn(icd->parent, |
675 | "Unsupported format code #%u: %d\n", idx, code); | 675 | "Unsupported format code #%u: 0x%x\n", idx, code); |
676 | return 0; | 676 | return 0; |
677 | } | 677 | } |
678 | 678 | ||
@@ -688,7 +688,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
688 | xlate->host_fmt = &mx3_camera_formats[0]; | 688 | xlate->host_fmt = &mx3_camera_formats[0]; |
689 | xlate->code = code; | 689 | xlate->code = code; |
690 | xlate++; | 690 | xlate++; |
691 | dev_dbg(dev, "Providing format %s using code %d\n", | 691 | dev_dbg(dev, "Providing format %s using code 0x%x\n", |
692 | mx3_camera_formats[0].name, code); | 692 | mx3_camera_formats[0].name, code); |
693 | } | 693 | } |
694 | break; | 694 | break; |
@@ -698,7 +698,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
698 | xlate->host_fmt = &mx3_camera_formats[1]; | 698 | xlate->host_fmt = &mx3_camera_formats[1]; |
699 | xlate->code = code; | 699 | xlate->code = code; |
700 | xlate++; | 700 | xlate++; |
701 | dev_dbg(dev, "Providing format %s using code %d\n", | 701 | dev_dbg(dev, "Providing format %s using code 0x%x\n", |
702 | mx3_camera_formats[1].name, code); | 702 | mx3_camera_formats[1].name, code); |
703 | } | 703 | } |
704 | break; | 704 | break; |
@@ -1144,6 +1144,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { | |||
1144 | 1144 | ||
1145 | static int mx3_camera_probe(struct platform_device *pdev) | 1145 | static int mx3_camera_probe(struct platform_device *pdev) |
1146 | { | 1146 | { |
1147 | struct mx3_camera_pdata *pdata = pdev->dev.platform_data; | ||
1147 | struct mx3_camera_dev *mx3_cam; | 1148 | struct mx3_camera_dev *mx3_cam; |
1148 | struct resource *res; | 1149 | struct resource *res; |
1149 | void __iomem *base; | 1150 | void __iomem *base; |
@@ -1151,26 +1152,25 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
1151 | struct soc_camera_host *soc_host; | 1152 | struct soc_camera_host *soc_host; |
1152 | 1153 | ||
1153 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1154 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1154 | if (!res) { | 1155 | base = devm_ioremap_resource(&pdev->dev, res); |
1155 | err = -ENODEV; | 1156 | if (IS_ERR(base)) |
1156 | goto egetres; | 1157 | return PTR_ERR(base); |
1157 | } | 1158 | |
1159 | if (!pdata) | ||
1160 | return -EINVAL; | ||
1158 | 1161 | ||
1159 | mx3_cam = vzalloc(sizeof(*mx3_cam)); | 1162 | mx3_cam = devm_kzalloc(&pdev->dev, sizeof(*mx3_cam), GFP_KERNEL); |
1160 | if (!mx3_cam) { | 1163 | if (!mx3_cam) { |
1161 | dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); | 1164 | dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); |
1162 | err = -ENOMEM; | 1165 | return -ENOMEM; |
1163 | goto ealloc; | ||
1164 | } | 1166 | } |
1165 | 1167 | ||
1166 | mx3_cam->clk = clk_get(&pdev->dev, NULL); | 1168 | mx3_cam->clk = devm_clk_get(&pdev->dev, NULL); |
1167 | if (IS_ERR(mx3_cam->clk)) { | 1169 | if (IS_ERR(mx3_cam->clk)) |
1168 | err = PTR_ERR(mx3_cam->clk); | 1170 | return PTR_ERR(mx3_cam->clk); |
1169 | goto eclkget; | ||
1170 | } | ||
1171 | 1171 | ||
1172 | mx3_cam->pdata = pdev->dev.platform_data; | 1172 | mx3_cam->pdata = pdata; |
1173 | mx3_cam->platform_flags = mx3_cam->pdata->flags; | 1173 | mx3_cam->platform_flags = pdata->flags; |
1174 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) { | 1174 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) { |
1175 | /* | 1175 | /* |
1176 | * Platform hasn't set available data widths. This is bad. | 1176 | * Platform hasn't set available data widths. This is bad. |
@@ -1189,7 +1189,7 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
1189 | if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) | 1189 | if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) |
1190 | mx3_cam->width_flags |= 1 << 14; | 1190 | mx3_cam->width_flags |= 1 << 14; |
1191 | 1191 | ||
1192 | mx3_cam->mclk = mx3_cam->pdata->mclk_10khz * 10000; | 1192 | mx3_cam->mclk = pdata->mclk_10khz * 10000; |
1193 | if (!mx3_cam->mclk) { | 1193 | if (!mx3_cam->mclk) { |
1194 | dev_warn(&pdev->dev, | 1194 | dev_warn(&pdev->dev, |
1195 | "mclk_10khz == 0! Please, fix your platform data. " | 1195 | "mclk_10khz == 0! Please, fix your platform data. " |
@@ -1201,13 +1201,6 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
1201 | INIT_LIST_HEAD(&mx3_cam->capture); | 1201 | INIT_LIST_HEAD(&mx3_cam->capture); |
1202 | spin_lock_init(&mx3_cam->lock); | 1202 | spin_lock_init(&mx3_cam->lock); |
1203 | 1203 | ||
1204 | base = ioremap(res->start, resource_size(res)); | ||
1205 | if (!base) { | ||
1206 | pr_err("Couldn't map %x@%x\n", resource_size(res), res->start); | ||
1207 | err = -ENOMEM; | ||
1208 | goto eioremap; | ||
1209 | } | ||
1210 | |||
1211 | mx3_cam->base = base; | 1204 | mx3_cam->base = base; |
1212 | 1205 | ||
1213 | soc_host = &mx3_cam->soc_host; | 1206 | soc_host = &mx3_cam->soc_host; |
@@ -1218,9 +1211,12 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
1218 | soc_host->nr = pdev->id; | 1211 | soc_host->nr = pdev->id; |
1219 | 1212 | ||
1220 | mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | 1213 | mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); |
1221 | if (IS_ERR(mx3_cam->alloc_ctx)) { | 1214 | if (IS_ERR(mx3_cam->alloc_ctx)) |
1222 | err = PTR_ERR(mx3_cam->alloc_ctx); | 1215 | return PTR_ERR(mx3_cam->alloc_ctx); |
1223 | goto eallocctx; | 1216 | |
1217 | if (pdata->asd_sizes) { | ||
1218 | soc_host->asd = pdata->asd; | ||
1219 | soc_host->asd_sizes = pdata->asd_sizes; | ||
1224 | } | 1220 | } |
1225 | 1221 | ||
1226 | err = soc_camera_host_register(soc_host); | 1222 | err = soc_camera_host_register(soc_host); |
@@ -1234,14 +1230,6 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
1234 | 1230 | ||
1235 | ecamhostreg: | 1231 | ecamhostreg: |
1236 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); | 1232 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); |
1237 | eallocctx: | ||
1238 | iounmap(base); | ||
1239 | eioremap: | ||
1240 | clk_put(mx3_cam->clk); | ||
1241 | eclkget: | ||
1242 | vfree(mx3_cam); | ||
1243 | ealloc: | ||
1244 | egetres: | ||
1245 | return err; | 1233 | return err; |
1246 | } | 1234 | } |
1247 | 1235 | ||
@@ -1251,12 +1239,8 @@ static int mx3_camera_remove(struct platform_device *pdev) | |||
1251 | struct mx3_camera_dev *mx3_cam = container_of(soc_host, | 1239 | struct mx3_camera_dev *mx3_cam = container_of(soc_host, |
1252 | struct mx3_camera_dev, soc_host); | 1240 | struct mx3_camera_dev, soc_host); |
1253 | 1241 | ||
1254 | clk_put(mx3_cam->clk); | ||
1255 | |||
1256 | soc_camera_host_unregister(soc_host); | 1242 | soc_camera_host_unregister(soc_host); |
1257 | 1243 | ||
1258 | iounmap(mx3_cam->base); | ||
1259 | |||
1260 | /* | 1244 | /* |
1261 | * The channel has either not been allocated, | 1245 | * The channel has either not been allocated, |
1262 | * or should have been released | 1246 | * or should have been released |
@@ -1266,8 +1250,6 @@ static int mx3_camera_remove(struct platform_device *pdev) | |||
1266 | 1250 | ||
1267 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); | 1251 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); |
1268 | 1252 | ||
1269 | vfree(mx3_cam); | ||
1270 | |||
1271 | dmaengine_put(); | 1253 | dmaengine_put(); |
1272 | 1254 | ||
1273 | return 0; | 1255 | return 0; |
@@ -1276,6 +1258,7 @@ static int mx3_camera_remove(struct platform_device *pdev) | |||
1276 | static struct platform_driver mx3_camera_driver = { | 1258 | static struct platform_driver mx3_camera_driver = { |
1277 | .driver = { | 1259 | .driver = { |
1278 | .name = MX3_CAM_DRV_NAME, | 1260 | .name = MX3_CAM_DRV_NAME, |
1261 | .owner = THIS_MODULE, | ||
1279 | }, | 1262 | }, |
1280 | .probe = mx3_camera_probe, | 1263 | .probe = mx3_camera_probe, |
1281 | .remove = mx3_camera_remove, | 1264 | .remove = mx3_camera_remove, |
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c new file mode 100644 index 000000000000..d02a7e0b773f --- /dev/null +++ b/drivers/media/platform/soc_camera/rcar_vin.c | |||
@@ -0,0 +1,1486 @@ | |||
1 | /* | ||
2 | * SoC-camera host driver for Renesas R-Car VIN unit | ||
3 | * | ||
4 | * Copyright (C) 2011-2013 Renesas Solutions Corp. | ||
5 | * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com> | ||
6 | * | ||
7 | * Based on V4L2 Driver for SuperH Mobile CEU interface "sh_mobile_ceu_camera.c" | ||
8 | * | ||
9 | * Copyright (C) 2008 Magnus Damm | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_data/camera-rcar.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/pm_runtime.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/videodev2.h> | ||
26 | |||
27 | #include <media/soc_camera.h> | ||
28 | #include <media/soc_mediabus.h> | ||
29 | #include <media/v4l2-common.h> | ||
30 | #include <media/v4l2-dev.h> | ||
31 | #include <media/v4l2-device.h> | ||
32 | #include <media/v4l2-mediabus.h> | ||
33 | #include <media/v4l2-subdev.h> | ||
34 | #include <media/videobuf2-dma-contig.h> | ||
35 | |||
36 | #include "soc_scale_crop.h" | ||
37 | |||
38 | #define DRV_NAME "rcar_vin" | ||
39 | |||
40 | /* Register offsets for R-Car VIN */ | ||
41 | #define VNMC_REG 0x00 /* Video n Main Control Register */ | ||
42 | #define VNMS_REG 0x04 /* Video n Module Status Register */ | ||
43 | #define VNFC_REG 0x08 /* Video n Frame Capture Register */ | ||
44 | #define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */ | ||
45 | #define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */ | ||
46 | #define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */ | ||
47 | #define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */ | ||
48 | #define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */ | ||
49 | #define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */ | ||
50 | #define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */ | ||
51 | #define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */ | ||
52 | #define VNIS_REG 0x2C /* Video n Image Stride Register */ | ||
53 | #define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */ | ||
54 | #define VNIE_REG 0x40 /* Video n Interrupt Enable Register */ | ||
55 | #define VNINTS_REG 0x44 /* Video n Interrupt Status Register */ | ||
56 | #define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */ | ||
57 | #define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */ | ||
58 | #define VNYS_REG 0x50 /* Video n Y Scale Register */ | ||
59 | #define VNXS_REG 0x54 /* Video n X Scale Register */ | ||
60 | #define VNDMR_REG 0x58 /* Video n Data Mode Register */ | ||
61 | #define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */ | ||
62 | #define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */ | ||
63 | |||
64 | /* Register bit fields for R-Car VIN */ | ||
65 | /* Video n Main Control Register bits */ | ||
66 | #define VNMC_FOC (1 << 21) | ||
67 | #define VNMC_YCAL (1 << 19) | ||
68 | #define VNMC_INF_YUV8_BT656 (0 << 16) | ||
69 | #define VNMC_INF_YUV8_BT601 (1 << 16) | ||
70 | #define VNMC_INF_YUV16 (5 << 16) | ||
71 | #define VNMC_VUP (1 << 10) | ||
72 | #define VNMC_IM_ODD (0 << 3) | ||
73 | #define VNMC_IM_ODD_EVEN (1 << 3) | ||
74 | #define VNMC_IM_EVEN (2 << 3) | ||
75 | #define VNMC_IM_FULL (3 << 3) | ||
76 | #define VNMC_BPS (1 << 1) | ||
77 | #define VNMC_ME (1 << 0) | ||
78 | |||
79 | /* Video n Module Status Register bits */ | ||
80 | #define VNMS_FBS_MASK (3 << 3) | ||
81 | #define VNMS_FBS_SHIFT 3 | ||
82 | #define VNMS_AV (1 << 1) | ||
83 | #define VNMS_CA (1 << 0) | ||
84 | |||
85 | /* Video n Frame Capture Register bits */ | ||
86 | #define VNFC_C_FRAME (1 << 1) | ||
87 | #define VNFC_S_FRAME (1 << 0) | ||
88 | |||
89 | /* Video n Interrupt Enable Register bits */ | ||
90 | #define VNIE_FIE (1 << 4) | ||
91 | #define VNIE_EFE (1 << 1) | ||
92 | |||
93 | /* Video n Data Mode Register bits */ | ||
94 | #define VNDMR_EXRGB (1 << 8) | ||
95 | #define VNDMR_BPSM (1 << 4) | ||
96 | #define VNDMR_DTMD_YCSEP (1 << 1) | ||
97 | #define VNDMR_DTMD_ARGB1555 (1 << 0) | ||
98 | |||
99 | /* Video n Data Mode Register 2 bits */ | ||
100 | #define VNDMR2_VPS (1 << 30) | ||
101 | #define VNDMR2_HPS (1 << 29) | ||
102 | #define VNDMR2_FTEV (1 << 17) | ||
103 | |||
104 | #define VIN_MAX_WIDTH 2048 | ||
105 | #define VIN_MAX_HEIGHT 2048 | ||
106 | |||
107 | enum chip_id { | ||
108 | RCAR_H1, | ||
109 | RCAR_M1, | ||
110 | RCAR_E1, | ||
111 | }; | ||
112 | |||
113 | enum rcar_vin_state { | ||
114 | STOPPED = 0, | ||
115 | RUNNING, | ||
116 | STOPPING, | ||
117 | }; | ||
118 | |||
119 | struct rcar_vin_priv { | ||
120 | void __iomem *base; | ||
121 | spinlock_t lock; | ||
122 | int sequence; | ||
123 | /* State of the VIN module in capturing mode */ | ||
124 | enum rcar_vin_state state; | ||
125 | struct rcar_vin_platform_data *pdata; | ||
126 | struct soc_camera_host ici; | ||
127 | struct list_head capture; | ||
128 | #define MAX_BUFFER_NUM 3 | ||
129 | struct vb2_buffer *queue_buf[MAX_BUFFER_NUM]; | ||
130 | struct vb2_alloc_ctx *alloc_ctx; | ||
131 | enum v4l2_field field; | ||
132 | unsigned int vb_count; | ||
133 | unsigned int nr_hw_slots; | ||
134 | bool request_to_stop; | ||
135 | struct completion capture_stop; | ||
136 | enum chip_id chip; | ||
137 | }; | ||
138 | |||
139 | #define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM) | ||
140 | |||
141 | struct rcar_vin_buffer { | ||
142 | struct vb2_buffer vb; | ||
143 | struct list_head list; | ||
144 | }; | ||
145 | |||
146 | #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \ | ||
147 | struct rcar_vin_buffer, \ | ||
148 | vb)->list) | ||
149 | |||
150 | struct rcar_vin_cam { | ||
151 | /* VIN offsets within the camera output, before the VIN scaler */ | ||
152 | unsigned int vin_left; | ||
153 | unsigned int vin_top; | ||
154 | /* Client output, as seen by the VIN */ | ||
155 | unsigned int width; | ||
156 | unsigned int height; | ||
157 | /* | ||
158 | * User window from S_CROP / G_CROP, produced by client cropping and | ||
159 | * scaling, VIN scaling and VIN cropping, mapped back onto the client | ||
160 | * input window | ||
161 | */ | ||
162 | struct v4l2_rect subrect; | ||
163 | /* Camera cropping rectangle */ | ||
164 | struct v4l2_rect rect; | ||
165 | const struct soc_mbus_pixelfmt *extra_fmt; | ||
166 | }; | ||
167 | |||
168 | /* | ||
169 | * .queue_setup() is called to check whether the driver can accept the requested | ||
170 | * number of buffers and to fill in plane sizes for the current frame format if | ||
171 | * required | ||
172 | */ | ||
173 | static int rcar_vin_videobuf_setup(struct vb2_queue *vq, | ||
174 | const struct v4l2_format *fmt, | ||
175 | unsigned int *count, | ||
176 | unsigned int *num_planes, | ||
177 | unsigned int sizes[], void *alloc_ctxs[]) | ||
178 | { | ||
179 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); | ||
180 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
181 | struct rcar_vin_priv *priv = ici->priv; | ||
182 | |||
183 | if (fmt) { | ||
184 | const struct soc_camera_format_xlate *xlate; | ||
185 | unsigned int bytes_per_line; | ||
186 | int ret; | ||
187 | |||
188 | xlate = soc_camera_xlate_by_fourcc(icd, | ||
189 | fmt->fmt.pix.pixelformat); | ||
190 | if (!xlate) | ||
191 | return -EINVAL; | ||
192 | ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width, | ||
193 | xlate->host_fmt); | ||
194 | if (ret < 0) | ||
195 | return ret; | ||
196 | |||
197 | bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret); | ||
198 | |||
199 | ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line, | ||
200 | fmt->fmt.pix.height); | ||
201 | if (ret < 0) | ||
202 | return ret; | ||
203 | |||
204 | sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret); | ||
205 | } else { | ||
206 | /* Called from VIDIOC_REQBUFS or in compatibility mode */ | ||
207 | sizes[0] = icd->sizeimage; | ||
208 | } | ||
209 | |||
210 | alloc_ctxs[0] = priv->alloc_ctx; | ||
211 | |||
212 | if (!vq->num_buffers) | ||
213 | priv->sequence = 0; | ||
214 | |||
215 | if (!*count) | ||
216 | *count = 2; | ||
217 | priv->vb_count = *count; | ||
218 | |||
219 | *num_planes = 1; | ||
220 | |||
221 | /* Number of hardware slots */ | ||
222 | if (is_continuous_transfer(priv)) | ||
223 | priv->nr_hw_slots = MAX_BUFFER_NUM; | ||
224 | else | ||
225 | priv->nr_hw_slots = 1; | ||
226 | |||
227 | dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int rcar_vin_setup(struct rcar_vin_priv *priv) | ||
233 | { | ||
234 | struct soc_camera_device *icd = priv->ici.icd; | ||
235 | struct rcar_vin_cam *cam = icd->host_priv; | ||
236 | u32 vnmc, dmr, interrupts; | ||
237 | bool progressive = false, output_is_yuv = false; | ||
238 | |||
239 | switch (priv->field) { | ||
240 | case V4L2_FIELD_TOP: | ||
241 | vnmc = VNMC_IM_ODD; | ||
242 | break; | ||
243 | case V4L2_FIELD_BOTTOM: | ||
244 | vnmc = VNMC_IM_EVEN; | ||
245 | break; | ||
246 | case V4L2_FIELD_INTERLACED: | ||
247 | case V4L2_FIELD_INTERLACED_TB: | ||
248 | vnmc = VNMC_IM_FULL; | ||
249 | break; | ||
250 | case V4L2_FIELD_INTERLACED_BT: | ||
251 | vnmc = VNMC_IM_FULL | VNMC_FOC; | ||
252 | break; | ||
253 | case V4L2_FIELD_NONE: | ||
254 | if (is_continuous_transfer(priv)) { | ||
255 | vnmc = VNMC_IM_ODD_EVEN; | ||
256 | progressive = true; | ||
257 | } else { | ||
258 | vnmc = VNMC_IM_ODD; | ||
259 | } | ||
260 | break; | ||
261 | default: | ||
262 | vnmc = VNMC_IM_ODD; | ||
263 | break; | ||
264 | } | ||
265 | |||
266 | /* input interface */ | ||
267 | switch (icd->current_fmt->code) { | ||
268 | case V4L2_MBUS_FMT_YUYV8_1X16: | ||
269 | /* BT.601/BT.1358 16bit YCbCr422 */ | ||
270 | vnmc |= VNMC_INF_YUV16; | ||
271 | break; | ||
272 | case V4L2_MBUS_FMT_YUYV8_2X8: | ||
273 | /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ | ||
274 | vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ? | ||
275 | VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601; | ||
276 | default: | ||
277 | break; | ||
278 | } | ||
279 | |||
280 | /* output format */ | ||
281 | switch (icd->current_fmt->host_fmt->fourcc) { | ||
282 | case V4L2_PIX_FMT_NV16: | ||
283 | iowrite32(ALIGN(cam->width * cam->height, 0x80), | ||
284 | priv->base + VNUVAOF_REG); | ||
285 | dmr = VNDMR_DTMD_YCSEP; | ||
286 | output_is_yuv = true; | ||
287 | break; | ||
288 | case V4L2_PIX_FMT_YUYV: | ||
289 | dmr = VNDMR_BPSM; | ||
290 | output_is_yuv = true; | ||
291 | break; | ||
292 | case V4L2_PIX_FMT_UYVY: | ||
293 | dmr = 0; | ||
294 | output_is_yuv = true; | ||
295 | break; | ||
296 | case V4L2_PIX_FMT_RGB555X: | ||
297 | dmr = VNDMR_DTMD_ARGB1555; | ||
298 | break; | ||
299 | case V4L2_PIX_FMT_RGB565: | ||
300 | dmr = 0; | ||
301 | break; | ||
302 | case V4L2_PIX_FMT_RGB32: | ||
303 | if (priv->chip == RCAR_H1 || priv->chip == RCAR_E1) { | ||
304 | dmr = VNDMR_EXRGB; | ||
305 | break; | ||
306 | } | ||
307 | default: | ||
308 | dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n", | ||
309 | icd->current_fmt->host_fmt->fourcc); | ||
310 | return -EINVAL; | ||
311 | } | ||
312 | |||
313 | /* Always update on field change */ | ||
314 | vnmc |= VNMC_VUP; | ||
315 | |||
316 | /* If input and output use the same colorspace, use bypass mode */ | ||
317 | if (output_is_yuv) | ||
318 | vnmc |= VNMC_BPS; | ||
319 | |||
320 | /* progressive or interlaced mode */ | ||
321 | interrupts = progressive ? VNIE_FIE | VNIE_EFE : VNIE_EFE; | ||
322 | |||
323 | /* ack interrupts */ | ||
324 | iowrite32(interrupts, priv->base + VNINTS_REG); | ||
325 | /* enable interrupts */ | ||
326 | iowrite32(interrupts, priv->base + VNIE_REG); | ||
327 | /* start capturing */ | ||
328 | iowrite32(dmr, priv->base + VNDMR_REG); | ||
329 | iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG); | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static void rcar_vin_capture(struct rcar_vin_priv *priv) | ||
335 | { | ||
336 | if (is_continuous_transfer(priv)) | ||
337 | /* Continuous Frame Capture Mode */ | ||
338 | iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG); | ||
339 | else | ||
340 | /* Single Frame Capture Mode */ | ||
341 | iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG); | ||
342 | } | ||
343 | |||
344 | static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv) | ||
345 | { | ||
346 | priv->state = STOPPING; | ||
347 | |||
348 | /* set continuous & single transfer off */ | ||
349 | iowrite32(0, priv->base + VNFC_REG); | ||
350 | /* disable capture (release DMA buffer), reset */ | ||
351 | iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME, | ||
352 | priv->base + VNMC_REG); | ||
353 | |||
354 | /* update the status if stopped already */ | ||
355 | if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA)) | ||
356 | priv->state = STOPPED; | ||
357 | } | ||
358 | |||
359 | static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv) | ||
360 | { | ||
361 | int slot; | ||
362 | |||
363 | for (slot = 0; slot < priv->nr_hw_slots; slot++) | ||
364 | if (priv->queue_buf[slot] == NULL) | ||
365 | return slot; | ||
366 | |||
367 | return -1; | ||
368 | } | ||
369 | |||
370 | static int rcar_vin_hw_ready(struct rcar_vin_priv *priv) | ||
371 | { | ||
372 | /* Ensure all HW slots are filled */ | ||
373 | return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0; | ||
374 | } | ||
375 | |||
376 | /* Moves a buffer from the queue to the HW slots */ | ||
377 | static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv) | ||
378 | { | ||
379 | struct vb2_buffer *vb; | ||
380 | dma_addr_t phys_addr_top; | ||
381 | int slot; | ||
382 | |||
383 | if (list_empty(&priv->capture)) | ||
384 | return 0; | ||
385 | |||
386 | /* Find a free HW slot */ | ||
387 | slot = rcar_vin_get_free_hw_slot(priv); | ||
388 | if (slot < 0) | ||
389 | return 0; | ||
390 | |||
391 | vb = &list_entry(priv->capture.next, struct rcar_vin_buffer, list)->vb; | ||
392 | list_del_init(to_buf_list(vb)); | ||
393 | priv->queue_buf[slot] = vb; | ||
394 | phys_addr_top = vb2_dma_contig_plane_dma_addr(vb, 0); | ||
395 | iowrite32(phys_addr_top, priv->base + VNMB_REG(slot)); | ||
396 | |||
397 | return 1; | ||
398 | } | ||
399 | |||
400 | static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) | ||
401 | { | ||
402 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); | ||
403 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
404 | struct rcar_vin_priv *priv = ici->priv; | ||
405 | unsigned long size; | ||
406 | |||
407 | size = icd->sizeimage; | ||
408 | |||
409 | if (vb2_plane_size(vb, 0) < size) { | ||
410 | dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n", | ||
411 | vb->v4l2_buf.index, vb2_plane_size(vb, 0), size); | ||
412 | goto error; | ||
413 | } | ||
414 | |||
415 | vb2_set_plane_payload(vb, 0, size); | ||
416 | |||
417 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, | ||
418 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); | ||
419 | |||
420 | spin_lock_irq(&priv->lock); | ||
421 | |||
422 | list_add_tail(to_buf_list(vb), &priv->capture); | ||
423 | rcar_vin_fill_hw_slot(priv); | ||
424 | |||
425 | /* If we weren't running, and have enough buffers, start capturing! */ | ||
426 | if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) { | ||
427 | if (rcar_vin_setup(priv)) { | ||
428 | /* Submit error */ | ||
429 | list_del_init(to_buf_list(vb)); | ||
430 | spin_unlock_irq(&priv->lock); | ||
431 | goto error; | ||
432 | } | ||
433 | priv->request_to_stop = false; | ||
434 | init_completion(&priv->capture_stop); | ||
435 | priv->state = RUNNING; | ||
436 | rcar_vin_capture(priv); | ||
437 | } | ||
438 | |||
439 | spin_unlock_irq(&priv->lock); | ||
440 | |||
441 | return; | ||
442 | |||
443 | error: | ||
444 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); | ||
445 | } | ||
446 | |||
447 | static void rcar_vin_videobuf_release(struct vb2_buffer *vb) | ||
448 | { | ||
449 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); | ||
450 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
451 | struct rcar_vin_priv *priv = ici->priv; | ||
452 | unsigned int i; | ||
453 | int buf_in_use = 0; | ||
454 | |||
455 | spin_lock_irq(&priv->lock); | ||
456 | |||
457 | /* Is the buffer in use by the VIN hardware? */ | ||
458 | for (i = 0; i < MAX_BUFFER_NUM; i++) { | ||
459 | if (priv->queue_buf[i] == vb) { | ||
460 | buf_in_use = 1; | ||
461 | break; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | if (buf_in_use) { | ||
466 | while (priv->state != STOPPED) { | ||
467 | |||
468 | /* issue stop if running */ | ||
469 | if (priv->state == RUNNING) | ||
470 | rcar_vin_request_capture_stop(priv); | ||
471 | |||
472 | /* wait until capturing has been stopped */ | ||
473 | if (priv->state == STOPPING) { | ||
474 | priv->request_to_stop = true; | ||
475 | spin_unlock_irq(&priv->lock); | ||
476 | wait_for_completion(&priv->capture_stop); | ||
477 | spin_lock_irq(&priv->lock); | ||
478 | } | ||
479 | } | ||
480 | /* | ||
481 | * Capturing has now stopped. The buffer we have been asked | ||
482 | * to release could be any of the current buffers in use, so | ||
483 | * release all buffers that are in use by HW | ||
484 | */ | ||
485 | for (i = 0; i < MAX_BUFFER_NUM; i++) { | ||
486 | if (priv->queue_buf[i]) { | ||
487 | vb2_buffer_done(priv->queue_buf[i], | ||
488 | VB2_BUF_STATE_ERROR); | ||
489 | priv->queue_buf[i] = NULL; | ||
490 | } | ||
491 | } | ||
492 | } else { | ||
493 | list_del_init(to_buf_list(vb)); | ||
494 | } | ||
495 | |||
496 | spin_unlock_irq(&priv->lock); | ||
497 | } | ||
498 | |||
499 | static int rcar_vin_videobuf_init(struct vb2_buffer *vb) | ||
500 | { | ||
501 | INIT_LIST_HEAD(to_buf_list(vb)); | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | static int rcar_vin_stop_streaming(struct vb2_queue *vq) | ||
506 | { | ||
507 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); | ||
508 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
509 | struct rcar_vin_priv *priv = ici->priv; | ||
510 | struct list_head *buf_head, *tmp; | ||
511 | |||
512 | spin_lock_irq(&priv->lock); | ||
513 | list_for_each_safe(buf_head, tmp, &priv->capture) | ||
514 | list_del_init(buf_head); | ||
515 | spin_unlock_irq(&priv->lock); | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static struct vb2_ops rcar_vin_vb2_ops = { | ||
521 | .queue_setup = rcar_vin_videobuf_setup, | ||
522 | .buf_init = rcar_vin_videobuf_init, | ||
523 | .buf_cleanup = rcar_vin_videobuf_release, | ||
524 | .buf_queue = rcar_vin_videobuf_queue, | ||
525 | .stop_streaming = rcar_vin_stop_streaming, | ||
526 | .wait_prepare = soc_camera_unlock, | ||
527 | .wait_finish = soc_camera_lock, | ||
528 | }; | ||
529 | |||
530 | static irqreturn_t rcar_vin_irq(int irq, void *data) | ||
531 | { | ||
532 | struct rcar_vin_priv *priv = data; | ||
533 | u32 int_status; | ||
534 | bool can_run = false, hw_stopped; | ||
535 | int slot; | ||
536 | unsigned int handled = 0; | ||
537 | |||
538 | spin_lock(&priv->lock); | ||
539 | |||
540 | int_status = ioread32(priv->base + VNINTS_REG); | ||
541 | if (!int_status) | ||
542 | goto done; | ||
543 | /* ack interrupts */ | ||
544 | iowrite32(int_status, priv->base + VNINTS_REG); | ||
545 | handled = 1; | ||
546 | |||
547 | /* nothing to do if capture status is 'STOPPED' */ | ||
548 | if (priv->state == STOPPED) | ||
549 | goto done; | ||
550 | |||
551 | hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA); | ||
552 | |||
553 | if (!priv->request_to_stop) { | ||
554 | if (is_continuous_transfer(priv)) | ||
555 | slot = (ioread32(priv->base + VNMS_REG) & | ||
556 | VNMS_FBS_MASK) >> VNMS_FBS_SHIFT; | ||
557 | else | ||
558 | slot = 0; | ||
559 | |||
560 | priv->queue_buf[slot]->v4l2_buf.field = priv->field; | ||
561 | priv->queue_buf[slot]->v4l2_buf.sequence = priv->sequence++; | ||
562 | do_gettimeofday(&priv->queue_buf[slot]->v4l2_buf.timestamp); | ||
563 | vb2_buffer_done(priv->queue_buf[slot], VB2_BUF_STATE_DONE); | ||
564 | priv->queue_buf[slot] = NULL; | ||
565 | |||
566 | if (priv->state != STOPPING) | ||
567 | can_run = rcar_vin_fill_hw_slot(priv); | ||
568 | |||
569 | if (hw_stopped || !can_run) { | ||
570 | priv->state = STOPPED; | ||
571 | } else if (is_continuous_transfer(priv) && | ||
572 | list_empty(&priv->capture) && | ||
573 | priv->state == RUNNING) { | ||
574 | /* | ||
575 | * The continuous capturing requires an explicit stop | ||
576 | * operation when there is no buffer to be set into | ||
577 | * the VnMBm registers. | ||
578 | */ | ||
579 | rcar_vin_request_capture_stop(priv); | ||
580 | } else { | ||
581 | rcar_vin_capture(priv); | ||
582 | } | ||
583 | |||
584 | } else if (hw_stopped) { | ||
585 | priv->state = STOPPED; | ||
586 | priv->request_to_stop = false; | ||
587 | complete(&priv->capture_stop); | ||
588 | } | ||
589 | |||
590 | done: | ||
591 | spin_unlock(&priv->lock); | ||
592 | |||
593 | return IRQ_RETVAL(handled); | ||
594 | } | ||
595 | |||
596 | static int rcar_vin_add_device(struct soc_camera_device *icd) | ||
597 | { | ||
598 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
599 | struct rcar_vin_priv *priv = ici->priv; | ||
600 | int i; | ||
601 | |||
602 | for (i = 0; i < MAX_BUFFER_NUM; i++) | ||
603 | priv->queue_buf[i] = NULL; | ||
604 | |||
605 | pm_runtime_get_sync(ici->v4l2_dev.dev); | ||
606 | |||
607 | dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n", | ||
608 | icd->devnum); | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static void rcar_vin_remove_device(struct soc_camera_device *icd) | ||
614 | { | ||
615 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
616 | struct rcar_vin_priv *priv = ici->priv; | ||
617 | struct vb2_buffer *vb; | ||
618 | int i; | ||
619 | |||
620 | /* disable capture, disable interrupts */ | ||
621 | iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME, | ||
622 | priv->base + VNMC_REG); | ||
623 | iowrite32(0, priv->base + VNIE_REG); | ||
624 | |||
625 | priv->state = STOPPED; | ||
626 | priv->request_to_stop = false; | ||
627 | |||
628 | /* make sure active buffer is cancelled */ | ||
629 | spin_lock_irq(&priv->lock); | ||
630 | for (i = 0; i < MAX_BUFFER_NUM; i++) { | ||
631 | vb = priv->queue_buf[i]; | ||
632 | if (vb) { | ||
633 | list_del_init(to_buf_list(vb)); | ||
634 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); | ||
635 | } | ||
636 | } | ||
637 | spin_unlock_irq(&priv->lock); | ||
638 | |||
639 | pm_runtime_put(ici->v4l2_dev.dev); | ||
640 | |||
641 | dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n", | ||
642 | icd->devnum); | ||
643 | } | ||
644 | |||
645 | /* Called with .host_lock held */ | ||
646 | static int rcar_vin_clock_start(struct soc_camera_host *ici) | ||
647 | { | ||
648 | /* VIN does not have "mclk" */ | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | /* Called with .host_lock held */ | ||
653 | static void rcar_vin_clock_stop(struct soc_camera_host *ici) | ||
654 | { | ||
655 | /* VIN does not have "mclk" */ | ||
656 | } | ||
657 | |||
658 | /* rect is guaranteed to not exceed the scaled camera rectangle */ | ||
659 | static int rcar_vin_set_rect(struct soc_camera_device *icd) | ||
660 | { | ||
661 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
662 | struct rcar_vin_cam *cam = icd->host_priv; | ||
663 | struct rcar_vin_priv *priv = ici->priv; | ||
664 | unsigned int left_offset, top_offset; | ||
665 | unsigned char dsize = 0; | ||
666 | struct v4l2_rect *cam_subrect = &cam->subrect; | ||
667 | |||
668 | dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n", | ||
669 | icd->user_width, icd->user_height, cam->vin_left, cam->vin_top); | ||
670 | |||
671 | left_offset = cam->vin_left; | ||
672 | top_offset = cam->vin_top; | ||
673 | |||
674 | if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB32 && | ||
675 | priv->chip == RCAR_E1) | ||
676 | dsize = 1; | ||
677 | |||
678 | dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n", | ||
679 | cam->width, cam->height, cam->vin_left, cam->vin_top); | ||
680 | dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n", | ||
681 | cam_subrect->width, cam_subrect->height, | ||
682 | cam_subrect->left, cam_subrect->top); | ||
683 | |||
684 | /* Set Start/End Pixel/Line Pre-Clip */ | ||
685 | iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG); | ||
686 | iowrite32((left_offset + cam->width - 1) << dsize, | ||
687 | priv->base + VNEPPRC_REG); | ||
688 | switch (priv->field) { | ||
689 | case V4L2_FIELD_INTERLACED: | ||
690 | case V4L2_FIELD_INTERLACED_TB: | ||
691 | case V4L2_FIELD_INTERLACED_BT: | ||
692 | iowrite32(top_offset / 2, priv->base + VNSLPRC_REG); | ||
693 | iowrite32((top_offset + cam->height) / 2 - 1, | ||
694 | priv->base + VNELPRC_REG); | ||
695 | break; | ||
696 | default: | ||
697 | iowrite32(top_offset, priv->base + VNSLPRC_REG); | ||
698 | iowrite32(top_offset + cam->height - 1, | ||
699 | priv->base + VNELPRC_REG); | ||
700 | break; | ||
701 | } | ||
702 | |||
703 | /* Set Start/End Pixel/Line Post-Clip */ | ||
704 | iowrite32(0, priv->base + VNSPPOC_REG); | ||
705 | iowrite32(0, priv->base + VNSLPOC_REG); | ||
706 | iowrite32((cam_subrect->width - 1) << dsize, priv->base + VNEPPOC_REG); | ||
707 | switch (priv->field) { | ||
708 | case V4L2_FIELD_INTERLACED: | ||
709 | case V4L2_FIELD_INTERLACED_TB: | ||
710 | case V4L2_FIELD_INTERLACED_BT: | ||
711 | iowrite32(cam_subrect->height / 2 - 1, | ||
712 | priv->base + VNELPOC_REG); | ||
713 | break; | ||
714 | default: | ||
715 | iowrite32(cam_subrect->height - 1, priv->base + VNELPOC_REG); | ||
716 | break; | ||
717 | } | ||
718 | |||
719 | iowrite32(ALIGN(cam->width, 0x10), priv->base + VNIS_REG); | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc) | ||
725 | { | ||
726 | *vnmc = ioread32(priv->base + VNMC_REG); | ||
727 | /* module disable */ | ||
728 | iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG); | ||
729 | } | ||
730 | |||
731 | static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc) | ||
732 | { | ||
733 | unsigned long timeout = jiffies + 10 * HZ; | ||
734 | |||
735 | /* | ||
736 | * Wait until the end of the current frame. It can take a long time, | ||
737 | * but if it has been aborted by a MRST1 reset, it should exit sooner. | ||
738 | */ | ||
739 | while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) && | ||
740 | time_before(jiffies, timeout)) | ||
741 | msleep(1); | ||
742 | |||
743 | if (time_after(jiffies, timeout)) { | ||
744 | dev_err(priv->ici.v4l2_dev.dev, | ||
745 | "Timeout waiting for frame end! Interface problem?\n"); | ||
746 | return; | ||
747 | } | ||
748 | |||
749 | iowrite32(vnmc, priv->base + VNMC_REG); | ||
750 | } | ||
751 | |||
752 | #define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \ | ||
753 | V4L2_MBUS_PCLK_SAMPLE_RISING | \ | ||
754 | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ | ||
755 | V4L2_MBUS_HSYNC_ACTIVE_LOW | \ | ||
756 | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ | ||
757 | V4L2_MBUS_VSYNC_ACTIVE_LOW | \ | ||
758 | V4L2_MBUS_DATA_ACTIVE_HIGH) | ||
759 | |||
760 | static int rcar_vin_set_bus_param(struct soc_camera_device *icd) | ||
761 | { | ||
762 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
763 | struct rcar_vin_priv *priv = ici->priv; | ||
764 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
765 | struct v4l2_mbus_config cfg; | ||
766 | unsigned long common_flags; | ||
767 | u32 vnmc; | ||
768 | u32 val; | ||
769 | int ret; | ||
770 | |||
771 | capture_stop_preserve(priv, &vnmc); | ||
772 | |||
773 | ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); | ||
774 | if (!ret) { | ||
775 | common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS); | ||
776 | if (!common_flags) { | ||
777 | dev_warn(icd->parent, | ||
778 | "MBUS flags incompatible: camera 0x%x, host 0x%x\n", | ||
779 | cfg.flags, VIN_MBUS_FLAGS); | ||
780 | return -EINVAL; | ||
781 | } | ||
782 | } else if (ret != -ENOIOCTLCMD) { | ||
783 | return ret; | ||
784 | } else { | ||
785 | common_flags = VIN_MBUS_FLAGS; | ||
786 | } | ||
787 | |||
788 | /* Make choises, based on platform preferences */ | ||
789 | if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && | ||
790 | (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { | ||
791 | if (priv->pdata->flags & RCAR_VIN_HSYNC_ACTIVE_LOW) | ||
792 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; | ||
793 | else | ||
794 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; | ||
795 | } | ||
796 | |||
797 | if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && | ||
798 | (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { | ||
799 | if (priv->pdata->flags & RCAR_VIN_VSYNC_ACTIVE_LOW) | ||
800 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; | ||
801 | else | ||
802 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; | ||
803 | } | ||
804 | |||
805 | cfg.flags = common_flags; | ||
806 | ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); | ||
807 | if (ret < 0 && ret != -ENOIOCTLCMD) | ||
808 | return ret; | ||
809 | |||
810 | val = priv->field == V4L2_FIELD_NONE ? VNDMR2_FTEV : 0; | ||
811 | if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) | ||
812 | val |= VNDMR2_VPS; | ||
813 | if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) | ||
814 | val |= VNDMR2_HPS; | ||
815 | iowrite32(val, priv->base + VNDMR2_REG); | ||
816 | |||
817 | ret = rcar_vin_set_rect(icd); | ||
818 | if (ret < 0) | ||
819 | return ret; | ||
820 | |||
821 | capture_restore(priv, vnmc); | ||
822 | |||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static int rcar_vin_try_bus_param(struct soc_camera_device *icd, | ||
827 | unsigned char buswidth) | ||
828 | { | ||
829 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
830 | struct v4l2_mbus_config cfg; | ||
831 | int ret; | ||
832 | |||
833 | ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); | ||
834 | if (ret == -ENOIOCTLCMD) | ||
835 | return 0; | ||
836 | else if (ret) | ||
837 | return ret; | ||
838 | |||
839 | if (buswidth > 24) | ||
840 | return -EINVAL; | ||
841 | |||
842 | /* check is there common mbus flags */ | ||
843 | ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS); | ||
844 | if (ret) | ||
845 | return 0; | ||
846 | |||
847 | dev_warn(icd->parent, | ||
848 | "MBUS flags incompatible: camera 0x%x, host 0x%x\n", | ||
849 | cfg.flags, VIN_MBUS_FLAGS); | ||
850 | |||
851 | return -EINVAL; | ||
852 | } | ||
853 | |||
854 | static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) | ||
855 | { | ||
856 | return fmt->packing == SOC_MBUS_PACKING_NONE || | ||
857 | (fmt->bits_per_sample > 8 && | ||
858 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); | ||
859 | } | ||
860 | |||
861 | static const struct soc_mbus_pixelfmt rcar_vin_formats[] = { | ||
862 | { | ||
863 | .fourcc = V4L2_PIX_FMT_NV16, | ||
864 | .name = "NV16", | ||
865 | .bits_per_sample = 8, | ||
866 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
867 | .order = SOC_MBUS_ORDER_LE, | ||
868 | .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C, | ||
869 | }, | ||
870 | { | ||
871 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
872 | .name = "UYVY", | ||
873 | .bits_per_sample = 16, | ||
874 | .packing = SOC_MBUS_PACKING_NONE, | ||
875 | .order = SOC_MBUS_ORDER_LE, | ||
876 | .layout = SOC_MBUS_LAYOUT_PACKED, | ||
877 | }, | ||
878 | { | ||
879 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
880 | .name = "RGB565", | ||
881 | .bits_per_sample = 16, | ||
882 | .packing = SOC_MBUS_PACKING_NONE, | ||
883 | .order = SOC_MBUS_ORDER_LE, | ||
884 | .layout = SOC_MBUS_LAYOUT_PACKED, | ||
885 | }, | ||
886 | { | ||
887 | .fourcc = V4L2_PIX_FMT_RGB555X, | ||
888 | .name = "ARGB1555", | ||
889 | .bits_per_sample = 16, | ||
890 | .packing = SOC_MBUS_PACKING_NONE, | ||
891 | .order = SOC_MBUS_ORDER_LE, | ||
892 | .layout = SOC_MBUS_LAYOUT_PACKED, | ||
893 | }, | ||
894 | { | ||
895 | .fourcc = V4L2_PIX_FMT_RGB32, | ||
896 | .name = "RGB888", | ||
897 | .bits_per_sample = 32, | ||
898 | .packing = SOC_MBUS_PACKING_NONE, | ||
899 | .order = SOC_MBUS_ORDER_LE, | ||
900 | .layout = SOC_MBUS_LAYOUT_PACKED, | ||
901 | }, | ||
902 | }; | ||
903 | |||
904 | static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, | ||
905 | struct soc_camera_format_xlate *xlate) | ||
906 | { | ||
907 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
908 | struct device *dev = icd->parent; | ||
909 | int ret, k, n; | ||
910 | int formats = 0; | ||
911 | struct rcar_vin_cam *cam; | ||
912 | enum v4l2_mbus_pixelcode code; | ||
913 | const struct soc_mbus_pixelfmt *fmt; | ||
914 | |||
915 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); | ||
916 | if (ret < 0) | ||
917 | return 0; | ||
918 | |||
919 | fmt = soc_mbus_get_fmtdesc(code); | ||
920 | if (!fmt) { | ||
921 | dev_warn(dev, "unsupported format code #%u: %d\n", idx, code); | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample); | ||
926 | if (ret < 0) | ||
927 | return 0; | ||
928 | |||
929 | if (!icd->host_priv) { | ||
930 | struct v4l2_mbus_framefmt mf; | ||
931 | struct v4l2_rect rect; | ||
932 | struct device *dev = icd->parent; | ||
933 | int shift; | ||
934 | |||
935 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | ||
936 | if (ret < 0) | ||
937 | return ret; | ||
938 | |||
939 | /* Cache current client geometry */ | ||
940 | ret = soc_camera_client_g_rect(sd, &rect); | ||
941 | if (ret == -ENOIOCTLCMD) { | ||
942 | /* Sensor driver doesn't support cropping */ | ||
943 | rect.left = 0; | ||
944 | rect.top = 0; | ||
945 | rect.width = mf.width; | ||
946 | rect.height = mf.height; | ||
947 | } else if (ret < 0) { | ||
948 | return ret; | ||
949 | } | ||
950 | |||
951 | /* | ||
952 | * If sensor proposes too large format then try smaller ones: | ||
953 | * 1280x960, 640x480, 320x240 | ||
954 | */ | ||
955 | for (shift = 0; shift < 3; shift++) { | ||
956 | if (mf.width <= VIN_MAX_WIDTH && | ||
957 | mf.height <= VIN_MAX_HEIGHT) | ||
958 | break; | ||
959 | |||
960 | mf.width = 1280 >> shift; | ||
961 | mf.height = 960 >> shift; | ||
962 | ret = v4l2_device_call_until_err(sd->v4l2_dev, | ||
963 | soc_camera_grp_id(icd), | ||
964 | video, s_mbus_fmt, | ||
965 | &mf); | ||
966 | if (ret < 0) | ||
967 | return ret; | ||
968 | } | ||
969 | |||
970 | if (shift == 3) { | ||
971 | dev_err(dev, | ||
972 | "Failed to configure the client below %ux%x\n", | ||
973 | mf.width, mf.height); | ||
974 | return -EIO; | ||
975 | } | ||
976 | |||
977 | dev_dbg(dev, "camera fmt %ux%u\n", mf.width, mf.height); | ||
978 | |||
979 | cam = kzalloc(sizeof(*cam), GFP_KERNEL); | ||
980 | if (!cam) | ||
981 | return -ENOMEM; | ||
982 | /* | ||
983 | * We are called with current camera crop, | ||
984 | * initialise subrect with it | ||
985 | */ | ||
986 | cam->rect = rect; | ||
987 | cam->subrect = rect; | ||
988 | cam->width = mf.width; | ||
989 | cam->height = mf.height; | ||
990 | |||
991 | icd->host_priv = cam; | ||
992 | } else { | ||
993 | cam = icd->host_priv; | ||
994 | } | ||
995 | |||
996 | /* Beginning of a pass */ | ||
997 | if (!idx) | ||
998 | cam->extra_fmt = NULL; | ||
999 | |||
1000 | switch (code) { | ||
1001 | case V4L2_MBUS_FMT_YUYV8_1X16: | ||
1002 | case V4L2_MBUS_FMT_YUYV8_2X8: | ||
1003 | if (cam->extra_fmt) | ||
1004 | break; | ||
1005 | |||
1006 | /* Add all our formats that can be generated by VIN */ | ||
1007 | cam->extra_fmt = rcar_vin_formats; | ||
1008 | |||
1009 | n = ARRAY_SIZE(rcar_vin_formats); | ||
1010 | formats += n; | ||
1011 | for (k = 0; xlate && k < n; k++, xlate++) { | ||
1012 | xlate->host_fmt = &rcar_vin_formats[k]; | ||
1013 | xlate->code = code; | ||
1014 | dev_dbg(dev, "Providing format %s using code %d\n", | ||
1015 | rcar_vin_formats[k].name, code); | ||
1016 | } | ||
1017 | break; | ||
1018 | default: | ||
1019 | if (!rcar_vin_packing_supported(fmt)) | ||
1020 | return 0; | ||
1021 | |||
1022 | dev_dbg(dev, "Providing format %s in pass-through mode\n", | ||
1023 | fmt->name); | ||
1024 | break; | ||
1025 | } | ||
1026 | |||
1027 | /* Generic pass-through */ | ||
1028 | formats++; | ||
1029 | if (xlate) { | ||
1030 | xlate->host_fmt = fmt; | ||
1031 | xlate->code = code; | ||
1032 | xlate++; | ||
1033 | } | ||
1034 | |||
1035 | return formats; | ||
1036 | } | ||
1037 | |||
1038 | static void rcar_vin_put_formats(struct soc_camera_device *icd) | ||
1039 | { | ||
1040 | kfree(icd->host_priv); | ||
1041 | icd->host_priv = NULL; | ||
1042 | } | ||
1043 | |||
1044 | static int rcar_vin_set_crop(struct soc_camera_device *icd, | ||
1045 | const struct v4l2_crop *a) | ||
1046 | { | ||
1047 | struct v4l2_crop a_writable = *a; | ||
1048 | const struct v4l2_rect *rect = &a_writable.c; | ||
1049 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1050 | struct rcar_vin_priv *priv = ici->priv; | ||
1051 | struct v4l2_crop cam_crop; | ||
1052 | struct rcar_vin_cam *cam = icd->host_priv; | ||
1053 | struct v4l2_rect *cam_rect = &cam_crop.c; | ||
1054 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1055 | struct device *dev = icd->parent; | ||
1056 | struct v4l2_mbus_framefmt mf; | ||
1057 | u32 vnmc; | ||
1058 | int ret, i; | ||
1059 | |||
1060 | dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height, | ||
1061 | rect->left, rect->top); | ||
1062 | |||
1063 | /* During camera cropping its output window can change too, stop VIN */ | ||
1064 | capture_stop_preserve(priv, &vnmc); | ||
1065 | dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc); | ||
1066 | |||
1067 | /* Apply iterative camera S_CROP for new input window. */ | ||
1068 | ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop, | ||
1069 | &cam->rect, &cam->subrect); | ||
1070 | if (ret < 0) | ||
1071 | return ret; | ||
1072 | |||
1073 | dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n", | ||
1074 | cam_rect->width, cam_rect->height, | ||
1075 | cam_rect->left, cam_rect->top); | ||
1076 | |||
1077 | /* On success cam_crop contains current camera crop */ | ||
1078 | |||
1079 | /* Retrieve camera output window */ | ||
1080 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | ||
1081 | if (ret < 0) | ||
1082 | return ret; | ||
1083 | |||
1084 | if (mf.width > VIN_MAX_WIDTH || mf.height > VIN_MAX_HEIGHT) | ||
1085 | return -EINVAL; | ||
1086 | |||
1087 | /* Cache camera output window */ | ||
1088 | cam->width = mf.width; | ||
1089 | cam->height = mf.height; | ||
1090 | |||
1091 | icd->user_width = cam->width; | ||
1092 | icd->user_height = cam->height; | ||
1093 | |||
1094 | cam->vin_left = rect->left & ~1; | ||
1095 | cam->vin_top = rect->top & ~1; | ||
1096 | |||
1097 | /* Use VIN cropping to crop to the new window. */ | ||
1098 | ret = rcar_vin_set_rect(icd); | ||
1099 | if (ret < 0) | ||
1100 | return ret; | ||
1101 | |||
1102 | cam->subrect = *rect; | ||
1103 | |||
1104 | dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n", | ||
1105 | icd->user_width, icd->user_height, | ||
1106 | cam->vin_left, cam->vin_top); | ||
1107 | |||
1108 | /* Restore capture */ | ||
1109 | for (i = 0; i < MAX_BUFFER_NUM; i++) { | ||
1110 | if (priv->queue_buf[i] && priv->state == STOPPED) { | ||
1111 | vnmc |= VNMC_ME; | ||
1112 | break; | ||
1113 | } | ||
1114 | } | ||
1115 | capture_restore(priv, vnmc); | ||
1116 | |||
1117 | /* Even if only camera cropping succeeded */ | ||
1118 | return ret; | ||
1119 | } | ||
1120 | |||
1121 | static int rcar_vin_get_crop(struct soc_camera_device *icd, | ||
1122 | struct v4l2_crop *a) | ||
1123 | { | ||
1124 | struct rcar_vin_cam *cam = icd->host_priv; | ||
1125 | |||
1126 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1127 | a->c = cam->subrect; | ||
1128 | |||
1129 | return 0; | ||
1130 | } | ||
1131 | |||
1132 | /* Similar to set_crop multistage iterative algorithm */ | ||
1133 | static int rcar_vin_set_fmt(struct soc_camera_device *icd, | ||
1134 | struct v4l2_format *f) | ||
1135 | { | ||
1136 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1137 | struct rcar_vin_priv *priv = ici->priv; | ||
1138 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1139 | struct rcar_vin_cam *cam = icd->host_priv; | ||
1140 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
1141 | struct v4l2_mbus_framefmt mf; | ||
1142 | struct device *dev = icd->parent; | ||
1143 | __u32 pixfmt = pix->pixelformat; | ||
1144 | const struct soc_camera_format_xlate *xlate; | ||
1145 | unsigned int vin_sub_width = 0, vin_sub_height = 0; | ||
1146 | int ret; | ||
1147 | bool can_scale; | ||
1148 | enum v4l2_field field; | ||
1149 | v4l2_std_id std; | ||
1150 | |||
1151 | dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n", | ||
1152 | pixfmt, pix->width, pix->height); | ||
1153 | |||
1154 | switch (pix->field) { | ||
1155 | default: | ||
1156 | pix->field = V4L2_FIELD_NONE; | ||
1157 | /* fall-through */ | ||
1158 | case V4L2_FIELD_NONE: | ||
1159 | case V4L2_FIELD_TOP: | ||
1160 | case V4L2_FIELD_BOTTOM: | ||
1161 | case V4L2_FIELD_INTERLACED_TB: | ||
1162 | case V4L2_FIELD_INTERLACED_BT: | ||
1163 | field = pix->field; | ||
1164 | break; | ||
1165 | case V4L2_FIELD_INTERLACED: | ||
1166 | /* Query for standard if not explicitly mentioned _TB/_BT */ | ||
1167 | ret = v4l2_subdev_call(sd, video, querystd, &std); | ||
1168 | if (ret < 0) | ||
1169 | std = V4L2_STD_625_50; | ||
1170 | |||
1171 | field = std & V4L2_STD_625_50 ? V4L2_FIELD_INTERLACED_TB : | ||
1172 | V4L2_FIELD_INTERLACED_BT; | ||
1173 | break; | ||
1174 | } | ||
1175 | |||
1176 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | ||
1177 | if (!xlate) { | ||
1178 | dev_warn(dev, "Format %x not found\n", pixfmt); | ||
1179 | return -EINVAL; | ||
1180 | } | ||
1181 | /* Calculate client output geometry */ | ||
1182 | soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf, | ||
1183 | 12); | ||
1184 | mf.field = pix->field; | ||
1185 | mf.colorspace = pix->colorspace; | ||
1186 | mf.code = xlate->code; | ||
1187 | |||
1188 | switch (pixfmt) { | ||
1189 | case V4L2_PIX_FMT_RGB32: | ||
1190 | can_scale = priv->chip != RCAR_E1; | ||
1191 | break; | ||
1192 | case V4L2_PIX_FMT_UYVY: | ||
1193 | case V4L2_PIX_FMT_YUYV: | ||
1194 | case V4L2_PIX_FMT_RGB565: | ||
1195 | case V4L2_PIX_FMT_RGB555X: | ||
1196 | can_scale = true; | ||
1197 | break; | ||
1198 | default: | ||
1199 | can_scale = false; | ||
1200 | break; | ||
1201 | } | ||
1202 | |||
1203 | dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height); | ||
1204 | |||
1205 | ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect, | ||
1206 | &mf, &vin_sub_width, &vin_sub_height, | ||
1207 | can_scale, 12); | ||
1208 | |||
1209 | /* Done with the camera. Now see if we can improve the result */ | ||
1210 | dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", | ||
1211 | ret, mf.width, mf.height, pix->width, pix->height); | ||
1212 | |||
1213 | if (ret == -ENOIOCTLCMD) | ||
1214 | dev_dbg(dev, "Sensor doesn't support scaling\n"); | ||
1215 | else if (ret < 0) | ||
1216 | return ret; | ||
1217 | |||
1218 | if (mf.code != xlate->code) | ||
1219 | return -EINVAL; | ||
1220 | |||
1221 | /* Prepare VIN crop */ | ||
1222 | cam->width = mf.width; | ||
1223 | cam->height = mf.height; | ||
1224 | |||
1225 | /* Use VIN scaling to scale to the requested user window. */ | ||
1226 | |||
1227 | /* We cannot scale up */ | ||
1228 | if (pix->width > vin_sub_width) | ||
1229 | vin_sub_width = pix->width; | ||
1230 | |||
1231 | if (pix->height > vin_sub_height) | ||
1232 | vin_sub_height = pix->height; | ||
1233 | |||
1234 | pix->colorspace = mf.colorspace; | ||
1235 | |||
1236 | if (!can_scale) { | ||
1237 | pix->width = vin_sub_width; | ||
1238 | pix->height = vin_sub_height; | ||
1239 | } | ||
1240 | |||
1241 | /* | ||
1242 | * We have calculated CFLCR, the actual configuration will be performed | ||
1243 | * in rcar_vin_set_bus_param() | ||
1244 | */ | ||
1245 | |||
1246 | dev_dbg(dev, "W: %u : %u, H: %u : %u\n", | ||
1247 | vin_sub_width, pix->width, vin_sub_height, pix->height); | ||
1248 | |||
1249 | icd->current_fmt = xlate; | ||
1250 | |||
1251 | priv->field = field; | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | static int rcar_vin_try_fmt(struct soc_camera_device *icd, | ||
1257 | struct v4l2_format *f) | ||
1258 | { | ||
1259 | const struct soc_camera_format_xlate *xlate; | ||
1260 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
1261 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1262 | struct v4l2_mbus_framefmt mf; | ||
1263 | __u32 pixfmt = pix->pixelformat; | ||
1264 | int width, height; | ||
1265 | int ret; | ||
1266 | |||
1267 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | ||
1268 | if (!xlate) { | ||
1269 | xlate = icd->current_fmt; | ||
1270 | dev_dbg(icd->parent, "Format %x not found, keeping %x\n", | ||
1271 | pixfmt, xlate->host_fmt->fourcc); | ||
1272 | pixfmt = xlate->host_fmt->fourcc; | ||
1273 | pix->pixelformat = pixfmt; | ||
1274 | pix->colorspace = icd->colorspace; | ||
1275 | } | ||
1276 | |||
1277 | /* FIXME: calculate using depth and bus width */ | ||
1278 | v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1, | ||
1279 | &pix->height, 4, VIN_MAX_HEIGHT, 2, 0); | ||
1280 | |||
1281 | width = pix->width; | ||
1282 | height = pix->height; | ||
1283 | |||
1284 | /* let soc-camera calculate these values */ | ||
1285 | pix->bytesperline = 0; | ||
1286 | pix->sizeimage = 0; | ||
1287 | |||
1288 | /* limit to sensor capabilities */ | ||
1289 | mf.width = pix->width; | ||
1290 | mf.height = pix->height; | ||
1291 | mf.field = pix->field; | ||
1292 | mf.code = xlate->code; | ||
1293 | mf.colorspace = pix->colorspace; | ||
1294 | |||
1295 | ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd), | ||
1296 | video, try_mbus_fmt, &mf); | ||
1297 | if (ret < 0) | ||
1298 | return ret; | ||
1299 | |||
1300 | pix->width = mf.width; | ||
1301 | pix->height = mf.height; | ||
1302 | pix->field = mf.field; | ||
1303 | pix->colorspace = mf.colorspace; | ||
1304 | |||
1305 | if (pixfmt == V4L2_PIX_FMT_NV16) { | ||
1306 | /* FIXME: check against rect_max after converting soc-camera */ | ||
1307 | /* We can scale precisely, need a bigger image from camera */ | ||
1308 | if (pix->width < width || pix->height < height) { | ||
1309 | /* | ||
1310 | * We presume, the sensor behaves sanely, i.e. if | ||
1311 | * requested a bigger rectangle, it will not return a | ||
1312 | * smaller one. | ||
1313 | */ | ||
1314 | mf.width = VIN_MAX_WIDTH; | ||
1315 | mf.height = VIN_MAX_HEIGHT; | ||
1316 | ret = v4l2_device_call_until_err(sd->v4l2_dev, | ||
1317 | soc_camera_grp_id(icd), | ||
1318 | video, try_mbus_fmt, | ||
1319 | &mf); | ||
1320 | if (ret < 0) { | ||
1321 | dev_err(icd->parent, | ||
1322 | "client try_fmt() = %d\n", ret); | ||
1323 | return ret; | ||
1324 | } | ||
1325 | } | ||
1326 | /* We will scale exactly */ | ||
1327 | if (mf.width > width) | ||
1328 | pix->width = width; | ||
1329 | if (mf.height > height) | ||
1330 | pix->height = height; | ||
1331 | } | ||
1332 | |||
1333 | return ret; | ||
1334 | } | ||
1335 | |||
1336 | static unsigned int rcar_vin_poll(struct file *file, poll_table *pt) | ||
1337 | { | ||
1338 | struct soc_camera_device *icd = file->private_data; | ||
1339 | |||
1340 | return vb2_poll(&icd->vb2_vidq, file, pt); | ||
1341 | } | ||
1342 | |||
1343 | static int rcar_vin_querycap(struct soc_camera_host *ici, | ||
1344 | struct v4l2_capability *cap) | ||
1345 | { | ||
1346 | strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card)); | ||
1347 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; | ||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | static int rcar_vin_init_videobuf2(struct vb2_queue *vq, | ||
1352 | struct soc_camera_device *icd) | ||
1353 | { | ||
1354 | vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1355 | vq->io_modes = VB2_MMAP | VB2_USERPTR; | ||
1356 | vq->drv_priv = icd; | ||
1357 | vq->ops = &rcar_vin_vb2_ops; | ||
1358 | vq->mem_ops = &vb2_dma_contig_memops; | ||
1359 | vq->buf_struct_size = sizeof(struct rcar_vin_buffer); | ||
1360 | vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1361 | |||
1362 | return vb2_queue_init(vq); | ||
1363 | } | ||
1364 | |||
1365 | static struct soc_camera_host_ops rcar_vin_host_ops = { | ||
1366 | .owner = THIS_MODULE, | ||
1367 | .add = rcar_vin_add_device, | ||
1368 | .remove = rcar_vin_remove_device, | ||
1369 | .clock_start = rcar_vin_clock_start, | ||
1370 | .clock_stop = rcar_vin_clock_stop, | ||
1371 | .get_formats = rcar_vin_get_formats, | ||
1372 | .put_formats = rcar_vin_put_formats, | ||
1373 | .get_crop = rcar_vin_get_crop, | ||
1374 | .set_crop = rcar_vin_set_crop, | ||
1375 | .try_fmt = rcar_vin_try_fmt, | ||
1376 | .set_fmt = rcar_vin_set_fmt, | ||
1377 | .poll = rcar_vin_poll, | ||
1378 | .querycap = rcar_vin_querycap, | ||
1379 | .set_bus_param = rcar_vin_set_bus_param, | ||
1380 | .init_videobuf2 = rcar_vin_init_videobuf2, | ||
1381 | }; | ||
1382 | |||
1383 | static struct platform_device_id rcar_vin_id_table[] = { | ||
1384 | { "r8a7779-vin", RCAR_H1 }, | ||
1385 | { "r8a7778-vin", RCAR_M1 }, | ||
1386 | { "uPD35004-vin", RCAR_E1 }, | ||
1387 | {}, | ||
1388 | }; | ||
1389 | MODULE_DEVICE_TABLE(platform, rcar_vin_id_table); | ||
1390 | |||
1391 | static int rcar_vin_probe(struct platform_device *pdev) | ||
1392 | { | ||
1393 | struct rcar_vin_priv *priv; | ||
1394 | struct resource *mem; | ||
1395 | struct rcar_vin_platform_data *pdata; | ||
1396 | int irq, ret; | ||
1397 | |||
1398 | pdata = pdev->dev.platform_data; | ||
1399 | if (!pdata || !pdata->flags) { | ||
1400 | dev_err(&pdev->dev, "platform data not set\n"); | ||
1401 | return -EINVAL; | ||
1402 | } | ||
1403 | |||
1404 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1405 | if (mem == NULL) | ||
1406 | return -EINVAL; | ||
1407 | |||
1408 | irq = platform_get_irq(pdev, 0); | ||
1409 | if (irq <= 0) | ||
1410 | return -EINVAL; | ||
1411 | |||
1412 | priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv), | ||
1413 | GFP_KERNEL); | ||
1414 | if (!priv) | ||
1415 | return -ENOMEM; | ||
1416 | |||
1417 | priv->base = devm_ioremap_resource(&pdev->dev, mem); | ||
1418 | if (IS_ERR(priv->base)) | ||
1419 | return PTR_ERR(priv->base); | ||
1420 | |||
1421 | ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED, | ||
1422 | dev_name(&pdev->dev), priv); | ||
1423 | if (ret) | ||
1424 | return ret; | ||
1425 | |||
1426 | priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
1427 | if (IS_ERR(priv->alloc_ctx)) | ||
1428 | return PTR_ERR(priv->alloc_ctx); | ||
1429 | |||
1430 | priv->ici.priv = priv; | ||
1431 | priv->ici.v4l2_dev.dev = &pdev->dev; | ||
1432 | priv->ici.nr = pdev->id; | ||
1433 | priv->ici.drv_name = dev_name(&pdev->dev); | ||
1434 | priv->ici.ops = &rcar_vin_host_ops; | ||
1435 | |||
1436 | priv->pdata = pdata; | ||
1437 | priv->chip = pdev->id_entry->driver_data; | ||
1438 | spin_lock_init(&priv->lock); | ||
1439 | INIT_LIST_HEAD(&priv->capture); | ||
1440 | |||
1441 | priv->state = STOPPED; | ||
1442 | |||
1443 | pm_suspend_ignore_children(&pdev->dev, true); | ||
1444 | pm_runtime_enable(&pdev->dev); | ||
1445 | |||
1446 | ret = soc_camera_host_register(&priv->ici); | ||
1447 | if (ret) | ||
1448 | goto cleanup; | ||
1449 | |||
1450 | return 0; | ||
1451 | |||
1452 | cleanup: | ||
1453 | pm_runtime_disable(&pdev->dev); | ||
1454 | vb2_dma_contig_cleanup_ctx(priv->alloc_ctx); | ||
1455 | |||
1456 | return ret; | ||
1457 | } | ||
1458 | |||
1459 | static int rcar_vin_remove(struct platform_device *pdev) | ||
1460 | { | ||
1461 | struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); | ||
1462 | struct rcar_vin_priv *priv = container_of(soc_host, | ||
1463 | struct rcar_vin_priv, ici); | ||
1464 | |||
1465 | soc_camera_host_unregister(soc_host); | ||
1466 | pm_runtime_disable(&pdev->dev); | ||
1467 | vb2_dma_contig_cleanup_ctx(priv->alloc_ctx); | ||
1468 | |||
1469 | return 0; | ||
1470 | } | ||
1471 | |||
1472 | static struct platform_driver rcar_vin_driver = { | ||
1473 | .probe = rcar_vin_probe, | ||
1474 | .remove = rcar_vin_remove, | ||
1475 | .driver = { | ||
1476 | .name = DRV_NAME, | ||
1477 | .owner = THIS_MODULE, | ||
1478 | }, | ||
1479 | .id_table = rcar_vin_id_table, | ||
1480 | }; | ||
1481 | |||
1482 | module_platform_driver(rcar_vin_driver); | ||
1483 | |||
1484 | MODULE_LICENSE("GPL"); | ||
1485 | MODULE_ALIAS("platform:rcar_vin"); | ||
1486 | MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver"); | ||
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index f2de0066089a..8df22f779175 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | |||
@@ -610,13 +610,12 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
610 | static int sh_mobile_ceu_clock_start(struct soc_camera_host *ici) | 610 | static int sh_mobile_ceu_clock_start(struct soc_camera_host *ici) |
611 | { | 611 | { |
612 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 612 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
613 | int ret; | ||
614 | 613 | ||
615 | pm_runtime_get_sync(ici->v4l2_dev.dev); | 614 | pm_runtime_get_sync(ici->v4l2_dev.dev); |
616 | 615 | ||
617 | pcdev->buf_total = 0; | 616 | pcdev->buf_total = 0; |
618 | 617 | ||
619 | ret = sh_mobile_ceu_soft_reset(pcdev); | 618 | sh_mobile_ceu_soft_reset(pcdev); |
620 | 619 | ||
621 | return 0; | 620 | return 0; |
622 | } | 621 | } |
@@ -1837,9 +1836,9 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) | |||
1837 | for (j = 0; pcdev->pdata->asd_sizes[j]; j++) { | 1836 | for (j = 0; pcdev->pdata->asd_sizes[j]; j++) { |
1838 | for (i = 0; i < pcdev->pdata->asd_sizes[j]; i++, asd++) { | 1837 | for (i = 0; i < pcdev->pdata->asd_sizes[j]; i++, asd++) { |
1839 | dev_dbg(&pdev->dev, "%s(): subdev #%d, type %u\n", | 1838 | dev_dbg(&pdev->dev, "%s(): subdev #%d, type %u\n", |
1840 | __func__, i, (*asd)->bus_type); | 1839 | __func__, i, (*asd)->match_type); |
1841 | if ((*asd)->bus_type == V4L2_ASYNC_BUS_PLATFORM && | 1840 | if ((*asd)->match_type == V4L2_ASYNC_MATCH_DEVNAME && |
1842 | !strncmp(name, (*asd)->match.platform.name, | 1841 | !strncmp(name, (*asd)->match.device_name.name, |
1843 | sizeof(name) - 1)) { | 1842 | sizeof(name) - 1)) { |
1844 | pcdev->csi2_asd = *asd; | 1843 | pcdev->csi2_asd = *asd; |
1845 | break; | 1844 | break; |
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 2dd0e5272941..387a232d95a4 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
@@ -136,7 +136,7 @@ EXPORT_SYMBOL(soc_camera_power_off); | |||
136 | 136 | ||
137 | int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) | 137 | int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) |
138 | { | 138 | { |
139 | 139 | /* Should not have any effect in synchronous case */ | |
140 | return devm_regulator_bulk_get(dev, ssdd->num_regulators, | 140 | return devm_regulator_bulk_get(dev, ssdd->num_regulators, |
141 | ssdd->regulators); | 141 | ssdd->regulators); |
142 | } | 142 | } |
@@ -1311,6 +1311,7 @@ eusrfmt: | |||
1311 | static int soc_camera_i2c_init(struct soc_camera_device *icd, | 1311 | static int soc_camera_i2c_init(struct soc_camera_device *icd, |
1312 | struct soc_camera_desc *sdesc) | 1312 | struct soc_camera_desc *sdesc) |
1313 | { | 1313 | { |
1314 | struct soc_camera_subdev_desc *ssdd; | ||
1314 | struct i2c_client *client; | 1315 | struct i2c_client *client; |
1315 | struct soc_camera_host *ici; | 1316 | struct soc_camera_host *ici; |
1316 | struct soc_camera_host_desc *shd = &sdesc->host_desc; | 1317 | struct soc_camera_host_desc *shd = &sdesc->host_desc; |
@@ -1333,7 +1334,21 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd, | |||
1333 | return -ENODEV; | 1334 | return -ENODEV; |
1334 | } | 1335 | } |
1335 | 1336 | ||
1336 | shd->board_info->platform_data = &sdesc->subdev_desc; | 1337 | ssdd = kzalloc(sizeof(*ssdd), GFP_KERNEL); |
1338 | if (!ssdd) { | ||
1339 | ret = -ENOMEM; | ||
1340 | goto ealloc; | ||
1341 | } | ||
1342 | |||
1343 | memcpy(ssdd, &sdesc->subdev_desc, sizeof(*ssdd)); | ||
1344 | /* | ||
1345 | * In synchronous case we request regulators ourselves in | ||
1346 | * soc_camera_pdrv_probe(), make sure the subdevice driver doesn't try | ||
1347 | * to allocate them again. | ||
1348 | */ | ||
1349 | ssdd->num_regulators = 0; | ||
1350 | ssdd->regulators = NULL; | ||
1351 | shd->board_info->platform_data = ssdd; | ||
1337 | 1352 | ||
1338 | snprintf(clk_name, sizeof(clk_name), "%d-%04x", | 1353 | snprintf(clk_name, sizeof(clk_name), "%d-%04x", |
1339 | shd->i2c_adapter_id, shd->board_info->addr); | 1354 | shd->i2c_adapter_id, shd->board_info->addr); |
@@ -1359,8 +1374,10 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd, | |||
1359 | return 0; | 1374 | return 0; |
1360 | ei2cnd: | 1375 | ei2cnd: |
1361 | v4l2_clk_unregister(icd->clk); | 1376 | v4l2_clk_unregister(icd->clk); |
1362 | eclkreg: | ||
1363 | icd->clk = NULL; | 1377 | icd->clk = NULL; |
1378 | eclkreg: | ||
1379 | kfree(ssdd); | ||
1380 | ealloc: | ||
1364 | i2c_put_adapter(adap); | 1381 | i2c_put_adapter(adap); |
1365 | return ret; | 1382 | return ret; |
1366 | } | 1383 | } |
@@ -1370,15 +1387,18 @@ static void soc_camera_i2c_free(struct soc_camera_device *icd) | |||
1370 | struct i2c_client *client = | 1387 | struct i2c_client *client = |
1371 | to_i2c_client(to_soc_camera_control(icd)); | 1388 | to_i2c_client(to_soc_camera_control(icd)); |
1372 | struct i2c_adapter *adap; | 1389 | struct i2c_adapter *adap; |
1390 | struct soc_camera_subdev_desc *ssdd; | ||
1373 | 1391 | ||
1374 | icd->control = NULL; | 1392 | icd->control = NULL; |
1375 | if (icd->sasc) | 1393 | if (icd->sasc) |
1376 | return; | 1394 | return; |
1377 | 1395 | ||
1378 | adap = client->adapter; | 1396 | adap = client->adapter; |
1397 | ssdd = client->dev.platform_data; | ||
1379 | v4l2_device_unregister_subdev(i2c_get_clientdata(client)); | 1398 | v4l2_device_unregister_subdev(i2c_get_clientdata(client)); |
1380 | i2c_unregister_device(client); | 1399 | i2c_unregister_device(client); |
1381 | i2c_put_adapter(adap); | 1400 | i2c_put_adapter(adap); |
1401 | kfree(ssdd); | ||
1382 | v4l2_clk_unregister(icd->clk); | 1402 | v4l2_clk_unregister(icd->clk); |
1383 | icd->clk = NULL; | 1403 | icd->clk = NULL; |
1384 | } | 1404 | } |
@@ -1466,7 +1486,8 @@ static int scan_async_group(struct soc_camera_host *ici, | |||
1466 | struct soc_camera_device *icd; | 1486 | struct soc_camera_device *icd; |
1467 | struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; | 1487 | struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; |
1468 | char clk_name[V4L2_SUBDEV_NAME_SIZE]; | 1488 | char clk_name[V4L2_SUBDEV_NAME_SIZE]; |
1469 | int ret, i; | 1489 | unsigned int i; |
1490 | int ret; | ||
1470 | 1491 | ||
1471 | /* First look for a sensor */ | 1492 | /* First look for a sensor */ |
1472 | for (i = 0; i < size; i++) { | 1493 | for (i = 0; i < size; i++) { |
@@ -1475,7 +1496,7 @@ static int scan_async_group(struct soc_camera_host *ici, | |||
1475 | break; | 1496 | break; |
1476 | } | 1497 | } |
1477 | 1498 | ||
1478 | if (i == size || asd[i]->bus_type != V4L2_ASYNC_BUS_I2C) { | 1499 | if (i >= size || asd[i]->match_type != V4L2_ASYNC_MATCH_I2C) { |
1479 | /* All useless */ | 1500 | /* All useless */ |
1480 | dev_err(ici->v4l2_dev.dev, "No I2C data source found!\n"); | 1501 | dev_err(ici->v4l2_dev.dev, "No I2C data source found!\n"); |
1481 | return -ENODEV; | 1502 | return -ENODEV; |
@@ -1501,7 +1522,7 @@ static int scan_async_group(struct soc_camera_host *ici, | |||
1501 | return -ENOMEM; | 1522 | return -ENOMEM; |
1502 | } | 1523 | } |
1503 | 1524 | ||
1504 | sasc->notifier.subdev = asd; | 1525 | sasc->notifier.subdevs = asd; |
1505 | sasc->notifier.num_subdevs = size; | 1526 | sasc->notifier.num_subdevs = size; |
1506 | sasc->notifier.bound = soc_camera_async_bound; | 1527 | sasc->notifier.bound = soc_camera_async_bound; |
1507 | sasc->notifier.unbind = soc_camera_async_unbind; | 1528 | sasc->notifier.unbind = soc_camera_async_unbind; |
@@ -1994,9 +2015,10 @@ static int soc_camera_pdrv_probe(struct platform_device *pdev) | |||
1994 | 2015 | ||
1995 | /* | 2016 | /* |
1996 | * In the asynchronous case ssdd->num_regulators == 0 yet, so, the below | 2017 | * In the asynchronous case ssdd->num_regulators == 0 yet, so, the below |
1997 | * regulator allocation is a dummy. They will be really requested later | 2018 | * regulator allocation is a dummy. They are actually requested by the |
1998 | * in soc_camera_async_bind(). Also note, that in that case regulators | 2019 | * subdevice driver, using soc_camera_power_init(). Also note, that in |
1999 | * are attached to the I2C device and not to the camera platform device. | 2020 | * that case regulators are attached to the I2C device and not to the |
2021 | * camera platform device. | ||
2000 | */ | 2022 | */ |
2001 | ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, | 2023 | ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, |
2002 | ssdd->regulators); | 2024 | ssdd->regulators); |
diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile new file mode 100644 index 000000000000..4da226169e15 --- /dev/null +++ b/drivers/media/platform/vsp1/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o | ||
2 | vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o | ||
3 | vsp1-y += vsp1_lif.o vsp1_uds.o | ||
4 | |||
5 | obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o | ||
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h new file mode 100644 index 000000000000..d6c6ecd039ff --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * vsp1.h -- R-Car VSP1 Driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | #ifndef __VSP1_H__ | ||
14 | #define __VSP1_H__ | ||
15 | |||
16 | #include <linux/io.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/mutex.h> | ||
19 | #include <linux/platform_data/vsp1.h> | ||
20 | |||
21 | #include <media/media-device.h> | ||
22 | #include <media/v4l2-device.h> | ||
23 | #include <media/v4l2-subdev.h> | ||
24 | |||
25 | #include "vsp1_regs.h" | ||
26 | |||
27 | struct clk; | ||
28 | struct device; | ||
29 | |||
30 | struct vsp1_platform_data; | ||
31 | struct vsp1_lif; | ||
32 | struct vsp1_rwpf; | ||
33 | struct vsp1_uds; | ||
34 | |||
35 | #define VPS1_MAX_RPF 5 | ||
36 | #define VPS1_MAX_UDS 3 | ||
37 | #define VPS1_MAX_WPF 4 | ||
38 | |||
39 | struct vsp1_device { | ||
40 | struct device *dev; | ||
41 | struct vsp1_platform_data *pdata; | ||
42 | |||
43 | void __iomem *mmio; | ||
44 | struct clk *clock; | ||
45 | struct clk *rt_clock; | ||
46 | |||
47 | struct mutex lock; | ||
48 | int ref_count; | ||
49 | |||
50 | struct vsp1_lif *lif; | ||
51 | struct vsp1_rwpf *rpf[VPS1_MAX_RPF]; | ||
52 | struct vsp1_uds *uds[VPS1_MAX_UDS]; | ||
53 | struct vsp1_rwpf *wpf[VPS1_MAX_WPF]; | ||
54 | |||
55 | struct list_head entities; | ||
56 | |||
57 | struct v4l2_device v4l2_dev; | ||
58 | struct media_device media_dev; | ||
59 | }; | ||
60 | |||
61 | struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1); | ||
62 | void vsp1_device_put(struct vsp1_device *vsp1); | ||
63 | |||
64 | static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg) | ||
65 | { | ||
66 | return ioread32(vsp1->mmio + reg); | ||
67 | } | ||
68 | |||
69 | static inline void vsp1_write(struct vsp1_device *vsp1, u32 reg, u32 data) | ||
70 | { | ||
71 | iowrite32(data, vsp1->mmio + reg); | ||
72 | } | ||
73 | |||
74 | #endif /* __VSP1_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c new file mode 100644 index 000000000000..1c9e771aa15c --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_drv.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * vsp1_drv.c -- R-Car VSP1 Driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/videodev2.h> | ||
21 | |||
22 | #include "vsp1.h" | ||
23 | #include "vsp1_lif.h" | ||
24 | #include "vsp1_rwpf.h" | ||
25 | #include "vsp1_uds.h" | ||
26 | |||
27 | /* ----------------------------------------------------------------------------- | ||
28 | * Interrupt Handling | ||
29 | */ | ||
30 | |||
31 | static irqreturn_t vsp1_irq_handler(int irq, void *data) | ||
32 | { | ||
33 | u32 mask = VI6_WFP_IRQ_STA_DFE | VI6_WFP_IRQ_STA_FRE; | ||
34 | struct vsp1_device *vsp1 = data; | ||
35 | irqreturn_t ret = IRQ_NONE; | ||
36 | unsigned int i; | ||
37 | |||
38 | for (i = 0; i < vsp1->pdata->wpf_count; ++i) { | ||
39 | struct vsp1_rwpf *wpf = vsp1->wpf[i]; | ||
40 | struct vsp1_pipeline *pipe; | ||
41 | u32 status; | ||
42 | |||
43 | if (wpf == NULL) | ||
44 | continue; | ||
45 | |||
46 | pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); | ||
47 | status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i)); | ||
48 | vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask); | ||
49 | |||
50 | if (status & VI6_WFP_IRQ_STA_FRE) { | ||
51 | vsp1_pipeline_frame_end(pipe); | ||
52 | ret = IRQ_HANDLED; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | /* ----------------------------------------------------------------------------- | ||
60 | * Entities | ||
61 | */ | ||
62 | |||
63 | /* | ||
64 | * vsp1_create_links - Create links from all sources to the given sink | ||
65 | * | ||
66 | * This function creates media links from all valid sources to the given sink | ||
67 | * pad. Links that would be invalid according to the VSP1 hardware capabilities | ||
68 | * are skipped. Those include all links | ||
69 | * | ||
70 | * - from a UDS to a UDS (UDS entities can't be chained) | ||
71 | * - from an entity to itself (no loops are allowed) | ||
72 | */ | ||
73 | static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) | ||
74 | { | ||
75 | struct media_entity *entity = &sink->subdev.entity; | ||
76 | struct vsp1_entity *source; | ||
77 | unsigned int pad; | ||
78 | int ret; | ||
79 | |||
80 | list_for_each_entry(source, &vsp1->entities, list_dev) { | ||
81 | u32 flags; | ||
82 | |||
83 | if (source->type == sink->type) | ||
84 | continue; | ||
85 | |||
86 | if (source->type == VSP1_ENTITY_LIF || | ||
87 | source->type == VSP1_ENTITY_WPF) | ||
88 | continue; | ||
89 | |||
90 | flags = source->type == VSP1_ENTITY_RPF && | ||
91 | sink->type == VSP1_ENTITY_WPF && | ||
92 | source->index == sink->index | ||
93 | ? MEDIA_LNK_FL_ENABLED : 0; | ||
94 | |||
95 | for (pad = 0; pad < entity->num_pads; ++pad) { | ||
96 | if (!(entity->pads[pad].flags & MEDIA_PAD_FL_SINK)) | ||
97 | continue; | ||
98 | |||
99 | ret = media_entity_create_link(&source->subdev.entity, | ||
100 | source->source_pad, | ||
101 | entity, pad, flags); | ||
102 | if (ret < 0) | ||
103 | return ret; | ||
104 | |||
105 | if (flags & MEDIA_LNK_FL_ENABLED) | ||
106 | source->sink = entity; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static void vsp1_destroy_entities(struct vsp1_device *vsp1) | ||
114 | { | ||
115 | struct vsp1_entity *entity; | ||
116 | struct vsp1_entity *next; | ||
117 | |||
118 | list_for_each_entry_safe(entity, next, &vsp1->entities, list_dev) { | ||
119 | list_del(&entity->list_dev); | ||
120 | vsp1_entity_destroy(entity); | ||
121 | } | ||
122 | |||
123 | v4l2_device_unregister(&vsp1->v4l2_dev); | ||
124 | media_device_unregister(&vsp1->media_dev); | ||
125 | } | ||
126 | |||
127 | static int vsp1_create_entities(struct vsp1_device *vsp1) | ||
128 | { | ||
129 | struct media_device *mdev = &vsp1->media_dev; | ||
130 | struct v4l2_device *vdev = &vsp1->v4l2_dev; | ||
131 | struct vsp1_entity *entity; | ||
132 | unsigned int i; | ||
133 | int ret; | ||
134 | |||
135 | mdev->dev = vsp1->dev; | ||
136 | strlcpy(mdev->model, "VSP1", sizeof(mdev->model)); | ||
137 | snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s", | ||
138 | dev_name(mdev->dev)); | ||
139 | ret = media_device_register(mdev); | ||
140 | if (ret < 0) { | ||
141 | dev_err(vsp1->dev, "media device registration failed (%d)\n", | ||
142 | ret); | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | vdev->mdev = mdev; | ||
147 | ret = v4l2_device_register(vsp1->dev, vdev); | ||
148 | if (ret < 0) { | ||
149 | dev_err(vsp1->dev, "V4L2 device registration failed (%d)\n", | ||
150 | ret); | ||
151 | goto done; | ||
152 | } | ||
153 | |||
154 | /* Instantiate all the entities. */ | ||
155 | if (vsp1->pdata->features & VSP1_HAS_LIF) { | ||
156 | vsp1->lif = vsp1_lif_create(vsp1); | ||
157 | if (IS_ERR(vsp1->lif)) { | ||
158 | ret = PTR_ERR(vsp1->lif); | ||
159 | goto done; | ||
160 | } | ||
161 | |||
162 | list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities); | ||
163 | } | ||
164 | |||
165 | for (i = 0; i < vsp1->pdata->rpf_count; ++i) { | ||
166 | struct vsp1_rwpf *rpf; | ||
167 | |||
168 | rpf = vsp1_rpf_create(vsp1, i); | ||
169 | if (IS_ERR(rpf)) { | ||
170 | ret = PTR_ERR(rpf); | ||
171 | goto done; | ||
172 | } | ||
173 | |||
174 | vsp1->rpf[i] = rpf; | ||
175 | list_add_tail(&rpf->entity.list_dev, &vsp1->entities); | ||
176 | } | ||
177 | |||
178 | for (i = 0; i < vsp1->pdata->uds_count; ++i) { | ||
179 | struct vsp1_uds *uds; | ||
180 | |||
181 | uds = vsp1_uds_create(vsp1, i); | ||
182 | if (IS_ERR(uds)) { | ||
183 | ret = PTR_ERR(uds); | ||
184 | goto done; | ||
185 | } | ||
186 | |||
187 | vsp1->uds[i] = uds; | ||
188 | list_add_tail(&uds->entity.list_dev, &vsp1->entities); | ||
189 | } | ||
190 | |||
191 | for (i = 0; i < vsp1->pdata->wpf_count; ++i) { | ||
192 | struct vsp1_rwpf *wpf; | ||
193 | |||
194 | wpf = vsp1_wpf_create(vsp1, i); | ||
195 | if (IS_ERR(wpf)) { | ||
196 | ret = PTR_ERR(wpf); | ||
197 | goto done; | ||
198 | } | ||
199 | |||
200 | vsp1->wpf[i] = wpf; | ||
201 | list_add_tail(&wpf->entity.list_dev, &vsp1->entities); | ||
202 | } | ||
203 | |||
204 | /* Create links. */ | ||
205 | list_for_each_entry(entity, &vsp1->entities, list_dev) { | ||
206 | if (entity->type == VSP1_ENTITY_LIF || | ||
207 | entity->type == VSP1_ENTITY_RPF) | ||
208 | continue; | ||
209 | |||
210 | ret = vsp1_create_links(vsp1, entity); | ||
211 | if (ret < 0) | ||
212 | goto done; | ||
213 | } | ||
214 | |||
215 | if (vsp1->pdata->features & VSP1_HAS_LIF) { | ||
216 | ret = media_entity_create_link( | ||
217 | &vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE, | ||
218 | &vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0); | ||
219 | if (ret < 0) | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | /* Register all subdevs. */ | ||
224 | list_for_each_entry(entity, &vsp1->entities, list_dev) { | ||
225 | ret = v4l2_device_register_subdev(&vsp1->v4l2_dev, | ||
226 | &entity->subdev); | ||
227 | if (ret < 0) | ||
228 | goto done; | ||
229 | } | ||
230 | |||
231 | ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); | ||
232 | |||
233 | done: | ||
234 | if (ret < 0) | ||
235 | vsp1_destroy_entities(vsp1); | ||
236 | |||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static int vsp1_device_init(struct vsp1_device *vsp1) | ||
241 | { | ||
242 | unsigned int i; | ||
243 | u32 status; | ||
244 | |||
245 | /* Reset any channel that might be running. */ | ||
246 | status = vsp1_read(vsp1, VI6_STATUS); | ||
247 | |||
248 | for (i = 0; i < vsp1->pdata->wpf_count; ++i) { | ||
249 | unsigned int timeout; | ||
250 | |||
251 | if (!(status & VI6_STATUS_SYS_ACT(i))) | ||
252 | continue; | ||
253 | |||
254 | vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(i)); | ||
255 | for (timeout = 10; timeout > 0; --timeout) { | ||
256 | status = vsp1_read(vsp1, VI6_STATUS); | ||
257 | if (!(status & VI6_STATUS_SYS_ACT(i))) | ||
258 | break; | ||
259 | |||
260 | usleep_range(1000, 2000); | ||
261 | } | ||
262 | |||
263 | if (!timeout) { | ||
264 | dev_err(vsp1->dev, "failed to reset wpf.%u\n", i); | ||
265 | return -ETIMEDOUT; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) | | ||
270 | (8 << VI6_CLK_DCSWT_CSTRW_SHIFT)); | ||
271 | |||
272 | for (i = 0; i < vsp1->pdata->rpf_count; ++i) | ||
273 | vsp1_write(vsp1, VI6_DPR_RPF_ROUTE(i), VI6_DPR_NODE_UNUSED); | ||
274 | |||
275 | for (i = 0; i < vsp1->pdata->uds_count; ++i) | ||
276 | vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED); | ||
277 | |||
278 | vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED); | ||
279 | vsp1_write(vsp1, VI6_DPR_LUT_ROUTE, VI6_DPR_NODE_UNUSED); | ||
280 | vsp1_write(vsp1, VI6_DPR_CLU_ROUTE, VI6_DPR_NODE_UNUSED); | ||
281 | vsp1_write(vsp1, VI6_DPR_HST_ROUTE, VI6_DPR_NODE_UNUSED); | ||
282 | vsp1_write(vsp1, VI6_DPR_HSI_ROUTE, VI6_DPR_NODE_UNUSED); | ||
283 | vsp1_write(vsp1, VI6_DPR_BRU_ROUTE, VI6_DPR_NODE_UNUSED); | ||
284 | |||
285 | vsp1_write(vsp1, VI6_DPR_HGO_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | | ||
286 | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); | ||
287 | vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | | ||
288 | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int vsp1_clocks_enable(struct vsp1_device *vsp1) | ||
294 | { | ||
295 | int ret; | ||
296 | |||
297 | ret = clk_prepare_enable(vsp1->clock); | ||
298 | if (ret < 0) | ||
299 | return ret; | ||
300 | |||
301 | if (IS_ERR(vsp1->rt_clock)) | ||
302 | return 0; | ||
303 | |||
304 | ret = clk_prepare_enable(vsp1->rt_clock); | ||
305 | if (ret < 0) { | ||
306 | clk_disable_unprepare(vsp1->clock); | ||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static void vsp1_clocks_disable(struct vsp1_device *vsp1) | ||
314 | { | ||
315 | if (!IS_ERR(vsp1->rt_clock)) | ||
316 | clk_disable_unprepare(vsp1->rt_clock); | ||
317 | clk_disable_unprepare(vsp1->clock); | ||
318 | } | ||
319 | |||
320 | /* | ||
321 | * vsp1_device_get - Acquire the VSP1 device | ||
322 | * | ||
323 | * Increment the VSP1 reference count and initialize the device if the first | ||
324 | * reference is taken. | ||
325 | * | ||
326 | * Return a pointer to the VSP1 device or NULL if an error occured. | ||
327 | */ | ||
328 | struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1) | ||
329 | { | ||
330 | struct vsp1_device *__vsp1 = vsp1; | ||
331 | int ret; | ||
332 | |||
333 | mutex_lock(&vsp1->lock); | ||
334 | if (vsp1->ref_count > 0) | ||
335 | goto done; | ||
336 | |||
337 | ret = vsp1_clocks_enable(vsp1); | ||
338 | if (ret < 0) { | ||
339 | __vsp1 = NULL; | ||
340 | goto done; | ||
341 | } | ||
342 | |||
343 | ret = vsp1_device_init(vsp1); | ||
344 | if (ret < 0) { | ||
345 | vsp1_clocks_disable(vsp1); | ||
346 | __vsp1 = NULL; | ||
347 | goto done; | ||
348 | } | ||
349 | |||
350 | done: | ||
351 | if (__vsp1) | ||
352 | vsp1->ref_count++; | ||
353 | |||
354 | mutex_unlock(&vsp1->lock); | ||
355 | return __vsp1; | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * vsp1_device_put - Release the VSP1 device | ||
360 | * | ||
361 | * Decrement the VSP1 reference count and cleanup the device if the last | ||
362 | * reference is released. | ||
363 | */ | ||
364 | void vsp1_device_put(struct vsp1_device *vsp1) | ||
365 | { | ||
366 | mutex_lock(&vsp1->lock); | ||
367 | |||
368 | if (--vsp1->ref_count == 0) | ||
369 | vsp1_clocks_disable(vsp1); | ||
370 | |||
371 | mutex_unlock(&vsp1->lock); | ||
372 | } | ||
373 | |||
374 | /* ----------------------------------------------------------------------------- | ||
375 | * Power Management | ||
376 | */ | ||
377 | |||
378 | #ifdef CONFIG_PM_SLEEP | ||
379 | static int vsp1_pm_suspend(struct device *dev) | ||
380 | { | ||
381 | struct vsp1_device *vsp1 = dev_get_drvdata(dev); | ||
382 | |||
383 | WARN_ON(mutex_is_locked(&vsp1->lock)); | ||
384 | |||
385 | if (vsp1->ref_count == 0) | ||
386 | return 0; | ||
387 | |||
388 | vsp1_clocks_disable(vsp1); | ||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static int vsp1_pm_resume(struct device *dev) | ||
393 | { | ||
394 | struct vsp1_device *vsp1 = dev_get_drvdata(dev); | ||
395 | |||
396 | WARN_ON(mutex_is_locked(&vsp1->lock)); | ||
397 | |||
398 | if (vsp1->ref_count) | ||
399 | return 0; | ||
400 | |||
401 | return vsp1_clocks_enable(vsp1); | ||
402 | } | ||
403 | #endif | ||
404 | |||
405 | static const struct dev_pm_ops vsp1_pm_ops = { | ||
406 | SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume) | ||
407 | }; | ||
408 | |||
409 | /* ----------------------------------------------------------------------------- | ||
410 | * Platform Driver | ||
411 | */ | ||
412 | |||
413 | static struct vsp1_platform_data * | ||
414 | vsp1_get_platform_data(struct platform_device *pdev) | ||
415 | { | ||
416 | struct vsp1_platform_data *pdata = pdev->dev.platform_data; | ||
417 | |||
418 | if (pdata == NULL) { | ||
419 | dev_err(&pdev->dev, "missing platform data\n"); | ||
420 | return NULL; | ||
421 | } | ||
422 | |||
423 | if (pdata->rpf_count <= 0 || pdata->rpf_count > VPS1_MAX_RPF) { | ||
424 | dev_err(&pdev->dev, "invalid number of RPF (%u)\n", | ||
425 | pdata->rpf_count); | ||
426 | return NULL; | ||
427 | } | ||
428 | |||
429 | if (pdata->uds_count <= 0 || pdata->uds_count > VPS1_MAX_UDS) { | ||
430 | dev_err(&pdev->dev, "invalid number of UDS (%u)\n", | ||
431 | pdata->uds_count); | ||
432 | return NULL; | ||
433 | } | ||
434 | |||
435 | if (pdata->wpf_count <= 0 || pdata->wpf_count > VPS1_MAX_WPF) { | ||
436 | dev_err(&pdev->dev, "invalid number of WPF (%u)\n", | ||
437 | pdata->wpf_count); | ||
438 | return NULL; | ||
439 | } | ||
440 | |||
441 | return pdata; | ||
442 | } | ||
443 | |||
444 | static int vsp1_probe(struct platform_device *pdev) | ||
445 | { | ||
446 | struct vsp1_device *vsp1; | ||
447 | struct resource *irq; | ||
448 | struct resource *io; | ||
449 | int ret; | ||
450 | |||
451 | vsp1 = devm_kzalloc(&pdev->dev, sizeof(*vsp1), GFP_KERNEL); | ||
452 | if (vsp1 == NULL) | ||
453 | return -ENOMEM; | ||
454 | |||
455 | vsp1->dev = &pdev->dev; | ||
456 | mutex_init(&vsp1->lock); | ||
457 | INIT_LIST_HEAD(&vsp1->entities); | ||
458 | |||
459 | vsp1->pdata = vsp1_get_platform_data(pdev); | ||
460 | if (vsp1->pdata == NULL) | ||
461 | return -ENODEV; | ||
462 | |||
463 | /* I/O, IRQ and clock resources */ | ||
464 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
465 | vsp1->mmio = devm_ioremap_resource(&pdev->dev, io); | ||
466 | if (IS_ERR(vsp1->mmio)) | ||
467 | return PTR_ERR(vsp1->mmio); | ||
468 | |||
469 | vsp1->clock = devm_clk_get(&pdev->dev, NULL); | ||
470 | if (IS_ERR(vsp1->clock)) { | ||
471 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
472 | return PTR_ERR(vsp1->clock); | ||
473 | } | ||
474 | |||
475 | /* The RT clock is optional */ | ||
476 | vsp1->rt_clock = devm_clk_get(&pdev->dev, "rt"); | ||
477 | |||
478 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
479 | if (!irq) { | ||
480 | dev_err(&pdev->dev, "missing IRQ\n"); | ||
481 | return -EINVAL; | ||
482 | } | ||
483 | |||
484 | ret = devm_request_irq(&pdev->dev, irq->start, vsp1_irq_handler, | ||
485 | IRQF_SHARED, dev_name(&pdev->dev), vsp1); | ||
486 | if (ret < 0) { | ||
487 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
488 | return ret; | ||
489 | } | ||
490 | |||
491 | /* Instanciate entities */ | ||
492 | ret = vsp1_create_entities(vsp1); | ||
493 | if (ret < 0) { | ||
494 | dev_err(&pdev->dev, "failed to create entities\n"); | ||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | platform_set_drvdata(pdev, vsp1); | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static int vsp1_remove(struct platform_device *pdev) | ||
504 | { | ||
505 | struct vsp1_device *vsp1 = platform_get_drvdata(pdev); | ||
506 | |||
507 | vsp1_destroy_entities(vsp1); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static struct platform_driver vsp1_platform_driver = { | ||
513 | .probe = vsp1_probe, | ||
514 | .remove = vsp1_remove, | ||
515 | .driver = { | ||
516 | .owner = THIS_MODULE, | ||
517 | .name = "vsp1", | ||
518 | .pm = &vsp1_pm_ops, | ||
519 | }, | ||
520 | }; | ||
521 | |||
522 | module_platform_driver(vsp1_platform_driver); | ||
523 | |||
524 | MODULE_ALIAS("vsp1"); | ||
525 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
526 | MODULE_DESCRIPTION("Renesas VSP1 Driver"); | ||
527 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c new file mode 100644 index 000000000000..9028f9d524f4 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_entity.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * vsp1_entity.c -- R-Car VSP1 Base Entity | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/gfp.h> | ||
16 | |||
17 | #include <media/media-entity.h> | ||
18 | #include <media/v4l2-subdev.h> | ||
19 | |||
20 | #include "vsp1.h" | ||
21 | #include "vsp1_entity.h" | ||
22 | |||
23 | /* ----------------------------------------------------------------------------- | ||
24 | * V4L2 Subdevice Operations | ||
25 | */ | ||
26 | |||
27 | struct v4l2_mbus_framefmt * | ||
28 | vsp1_entity_get_pad_format(struct vsp1_entity *entity, | ||
29 | struct v4l2_subdev_fh *fh, | ||
30 | unsigned int pad, u32 which) | ||
31 | { | ||
32 | switch (which) { | ||
33 | case V4L2_SUBDEV_FORMAT_TRY: | ||
34 | return v4l2_subdev_get_try_format(fh, pad); | ||
35 | case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
36 | return &entity->formats[pad]; | ||
37 | default: | ||
38 | return NULL; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * vsp1_entity_init_formats - Initialize formats on all pads | ||
44 | * @subdev: V4L2 subdevice | ||
45 | * @fh: V4L2 subdev file handle | ||
46 | * | ||
47 | * Initialize all pad formats with default values. If fh is not NULL, try | ||
48 | * formats are initialized on the file handle. Otherwise active formats are | ||
49 | * initialized on the device. | ||
50 | */ | ||
51 | void vsp1_entity_init_formats(struct v4l2_subdev *subdev, | ||
52 | struct v4l2_subdev_fh *fh) | ||
53 | { | ||
54 | struct v4l2_subdev_format format; | ||
55 | unsigned int pad; | ||
56 | |||
57 | for (pad = 0; pad < subdev->entity.num_pads - 1; ++pad) { | ||
58 | memset(&format, 0, sizeof(format)); | ||
59 | |||
60 | format.pad = pad; | ||
61 | format.which = fh ? V4L2_SUBDEV_FORMAT_TRY | ||
62 | : V4L2_SUBDEV_FORMAT_ACTIVE; | ||
63 | |||
64 | v4l2_subdev_call(subdev, pad, set_fmt, fh, &format); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static int vsp1_entity_open(struct v4l2_subdev *subdev, | ||
69 | struct v4l2_subdev_fh *fh) | ||
70 | { | ||
71 | vsp1_entity_init_formats(subdev, fh); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops = { | ||
77 | .open = vsp1_entity_open, | ||
78 | }; | ||
79 | |||
80 | /* ----------------------------------------------------------------------------- | ||
81 | * Media Operations | ||
82 | */ | ||
83 | |||
84 | static int vsp1_entity_link_setup(struct media_entity *entity, | ||
85 | const struct media_pad *local, | ||
86 | const struct media_pad *remote, u32 flags) | ||
87 | { | ||
88 | struct vsp1_entity *source; | ||
89 | |||
90 | if (!(local->flags & MEDIA_PAD_FL_SOURCE)) | ||
91 | return 0; | ||
92 | |||
93 | source = container_of(local->entity, struct vsp1_entity, subdev.entity); | ||
94 | |||
95 | if (!source->route) | ||
96 | return 0; | ||
97 | |||
98 | if (flags & MEDIA_LNK_FL_ENABLED) { | ||
99 | if (source->sink) | ||
100 | return -EBUSY; | ||
101 | source->sink = remote->entity; | ||
102 | } else { | ||
103 | source->sink = NULL; | ||
104 | } | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | const struct media_entity_operations vsp1_media_ops = { | ||
110 | .link_setup = vsp1_entity_link_setup, | ||
111 | .link_validate = v4l2_subdev_link_validate, | ||
112 | }; | ||
113 | |||
114 | /* ----------------------------------------------------------------------------- | ||
115 | * Initialization | ||
116 | */ | ||
117 | |||
118 | int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, | ||
119 | unsigned int num_pads) | ||
120 | { | ||
121 | static const struct { | ||
122 | unsigned int id; | ||
123 | unsigned int reg; | ||
124 | } routes[] = { | ||
125 | { VI6_DPR_NODE_LIF, 0 }, | ||
126 | { VI6_DPR_NODE_RPF(0), VI6_DPR_RPF_ROUTE(0) }, | ||
127 | { VI6_DPR_NODE_RPF(1), VI6_DPR_RPF_ROUTE(1) }, | ||
128 | { VI6_DPR_NODE_RPF(2), VI6_DPR_RPF_ROUTE(2) }, | ||
129 | { VI6_DPR_NODE_RPF(3), VI6_DPR_RPF_ROUTE(3) }, | ||
130 | { VI6_DPR_NODE_RPF(4), VI6_DPR_RPF_ROUTE(4) }, | ||
131 | { VI6_DPR_NODE_UDS(0), VI6_DPR_UDS_ROUTE(0) }, | ||
132 | { VI6_DPR_NODE_UDS(1), VI6_DPR_UDS_ROUTE(1) }, | ||
133 | { VI6_DPR_NODE_UDS(2), VI6_DPR_UDS_ROUTE(2) }, | ||
134 | { VI6_DPR_NODE_WPF(0), 0 }, | ||
135 | { VI6_DPR_NODE_WPF(1), 0 }, | ||
136 | { VI6_DPR_NODE_WPF(2), 0 }, | ||
137 | { VI6_DPR_NODE_WPF(3), 0 }, | ||
138 | }; | ||
139 | |||
140 | unsigned int i; | ||
141 | |||
142 | for (i = 0; i < ARRAY_SIZE(routes); ++i) { | ||
143 | if (routes[i].id == entity->id) { | ||
144 | entity->route = routes[i].reg; | ||
145 | break; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | if (i == ARRAY_SIZE(routes)) | ||
150 | return -EINVAL; | ||
151 | |||
152 | entity->vsp1 = vsp1; | ||
153 | entity->source_pad = num_pads - 1; | ||
154 | |||
155 | /* Allocate formats and pads. */ | ||
156 | entity->formats = devm_kzalloc(vsp1->dev, | ||
157 | num_pads * sizeof(*entity->formats), | ||
158 | GFP_KERNEL); | ||
159 | if (entity->formats == NULL) | ||
160 | return -ENOMEM; | ||
161 | |||
162 | entity->pads = devm_kzalloc(vsp1->dev, num_pads * sizeof(*entity->pads), | ||
163 | GFP_KERNEL); | ||
164 | if (entity->pads == NULL) | ||
165 | return -ENOMEM; | ||
166 | |||
167 | /* Initialize pads. */ | ||
168 | for (i = 0; i < num_pads - 1; ++i) | ||
169 | entity->pads[i].flags = MEDIA_PAD_FL_SINK; | ||
170 | |||
171 | entity->pads[num_pads - 1].flags = MEDIA_PAD_FL_SOURCE; | ||
172 | |||
173 | /* Initialize the media entity. */ | ||
174 | return media_entity_init(&entity->subdev.entity, num_pads, | ||
175 | entity->pads, 0); | ||
176 | } | ||
177 | |||
178 | void vsp1_entity_destroy(struct vsp1_entity *entity) | ||
179 | { | ||
180 | media_entity_cleanup(&entity->subdev.entity); | ||
181 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h new file mode 100644 index 000000000000..c4feab2cbb81 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_entity.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * vsp1_entity.h -- R-Car VSP1 Base Entity | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | #ifndef __VSP1_ENTITY_H__ | ||
14 | #define __VSP1_ENTITY_H__ | ||
15 | |||
16 | #include <linux/list.h> | ||
17 | |||
18 | #include <media/v4l2-subdev.h> | ||
19 | |||
20 | struct vsp1_device; | ||
21 | |||
22 | enum vsp1_entity_type { | ||
23 | VSP1_ENTITY_LIF, | ||
24 | VSP1_ENTITY_RPF, | ||
25 | VSP1_ENTITY_UDS, | ||
26 | VSP1_ENTITY_WPF, | ||
27 | }; | ||
28 | |||
29 | struct vsp1_entity { | ||
30 | struct vsp1_device *vsp1; | ||
31 | |||
32 | enum vsp1_entity_type type; | ||
33 | unsigned int index; | ||
34 | unsigned int id; | ||
35 | unsigned int route; | ||
36 | |||
37 | struct list_head list_dev; | ||
38 | struct list_head list_pipe; | ||
39 | |||
40 | struct media_pad *pads; | ||
41 | unsigned int source_pad; | ||
42 | |||
43 | struct media_entity *sink; | ||
44 | |||
45 | struct v4l2_subdev subdev; | ||
46 | struct v4l2_mbus_framefmt *formats; | ||
47 | }; | ||
48 | |||
49 | static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) | ||
50 | { | ||
51 | return container_of(subdev, struct vsp1_entity, subdev); | ||
52 | } | ||
53 | |||
54 | int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, | ||
55 | unsigned int num_pads); | ||
56 | void vsp1_entity_destroy(struct vsp1_entity *entity); | ||
57 | |||
58 | extern const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops; | ||
59 | extern const struct media_entity_operations vsp1_media_ops; | ||
60 | |||
61 | struct v4l2_mbus_framefmt * | ||
62 | vsp1_entity_get_pad_format(struct vsp1_entity *entity, | ||
63 | struct v4l2_subdev_fh *fh, | ||
64 | unsigned int pad, u32 which); | ||
65 | void vsp1_entity_init_formats(struct v4l2_subdev *subdev, | ||
66 | struct v4l2_subdev_fh *fh); | ||
67 | |||
68 | #endif /* __VSP1_ENTITY_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c new file mode 100644 index 000000000000..74a32e69ef10 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_lif.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * vsp1_lif.c -- R-Car VSP1 LCD Controller Interface | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/gfp.h> | ||
16 | |||
17 | #include <media/v4l2-subdev.h> | ||
18 | |||
19 | #include "vsp1.h" | ||
20 | #include "vsp1_lif.h" | ||
21 | |||
22 | #define LIF_MIN_SIZE 2U | ||
23 | #define LIF_MAX_SIZE 2048U | ||
24 | |||
25 | /* ----------------------------------------------------------------------------- | ||
26 | * Device Access | ||
27 | */ | ||
28 | |||
29 | static inline u32 vsp1_lif_read(struct vsp1_lif *lif, u32 reg) | ||
30 | { | ||
31 | return vsp1_read(lif->entity.vsp1, reg); | ||
32 | } | ||
33 | |||
34 | static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data) | ||
35 | { | ||
36 | vsp1_write(lif->entity.vsp1, reg, data); | ||
37 | } | ||
38 | |||
39 | /* ----------------------------------------------------------------------------- | ||
40 | * V4L2 Subdevice Core Operations | ||
41 | */ | ||
42 | |||
43 | static int lif_s_stream(struct v4l2_subdev *subdev, int enable) | ||
44 | { | ||
45 | const struct v4l2_mbus_framefmt *format; | ||
46 | struct vsp1_lif *lif = to_lif(subdev); | ||
47 | unsigned int hbth = 1300; | ||
48 | unsigned int obth = 400; | ||
49 | unsigned int lbth = 200; | ||
50 | |||
51 | if (!enable) { | ||
52 | vsp1_lif_write(lif, VI6_LIF_CTRL, 0); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | format = &lif->entity.formats[LIF_PAD_SOURCE]; | ||
57 | |||
58 | obth = min(obth, (format->width + 1) / 2 * format->height - 4); | ||
59 | |||
60 | vsp1_lif_write(lif, VI6_LIF_CSBTH, | ||
61 | (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) | | ||
62 | (lbth << VI6_LIF_CSBTH_LBTH_SHIFT)); | ||
63 | |||
64 | vsp1_lif_write(lif, VI6_LIF_CTRL, | ||
65 | (obth << VI6_LIF_CTRL_OBTH_SHIFT) | | ||
66 | (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | | ||
67 | VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /* ----------------------------------------------------------------------------- | ||
73 | * V4L2 Subdevice Pad Operations | ||
74 | */ | ||
75 | |||
76 | static int lif_enum_mbus_code(struct v4l2_subdev *subdev, | ||
77 | struct v4l2_subdev_fh *fh, | ||
78 | struct v4l2_subdev_mbus_code_enum *code) | ||
79 | { | ||
80 | static const unsigned int codes[] = { | ||
81 | V4L2_MBUS_FMT_ARGB8888_1X32, | ||
82 | V4L2_MBUS_FMT_AYUV8_1X32, | ||
83 | }; | ||
84 | |||
85 | if (code->pad == LIF_PAD_SINK) { | ||
86 | if (code->index >= ARRAY_SIZE(codes)) | ||
87 | return -EINVAL; | ||
88 | |||
89 | code->code = codes[code->index]; | ||
90 | } else { | ||
91 | struct v4l2_mbus_framefmt *format; | ||
92 | |||
93 | /* The LIF can't perform format conversion, the sink format is | ||
94 | * always identical to the source format. | ||
95 | */ | ||
96 | if (code->index) | ||
97 | return -EINVAL; | ||
98 | |||
99 | format = v4l2_subdev_get_try_format(fh, LIF_PAD_SINK); | ||
100 | code->code = format->code; | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int lif_enum_frame_size(struct v4l2_subdev *subdev, | ||
107 | struct v4l2_subdev_fh *fh, | ||
108 | struct v4l2_subdev_frame_size_enum *fse) | ||
109 | { | ||
110 | struct v4l2_mbus_framefmt *format; | ||
111 | |||
112 | format = v4l2_subdev_get_try_format(fh, LIF_PAD_SINK); | ||
113 | |||
114 | if (fse->index || fse->code != format->code) | ||
115 | return -EINVAL; | ||
116 | |||
117 | if (fse->pad == LIF_PAD_SINK) { | ||
118 | fse->min_width = LIF_MIN_SIZE; | ||
119 | fse->max_width = LIF_MAX_SIZE; | ||
120 | fse->min_height = LIF_MIN_SIZE; | ||
121 | fse->max_height = LIF_MAX_SIZE; | ||
122 | } else { | ||
123 | fse->min_width = format->width; | ||
124 | fse->max_width = format->width; | ||
125 | fse->min_height = format->height; | ||
126 | fse->max_height = format->height; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int lif_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
133 | struct v4l2_subdev_format *fmt) | ||
134 | { | ||
135 | struct vsp1_lif *lif = to_lif(subdev); | ||
136 | |||
137 | fmt->format = *vsp1_entity_get_pad_format(&lif->entity, fh, fmt->pad, | ||
138 | fmt->which); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
144 | struct v4l2_subdev_format *fmt) | ||
145 | { | ||
146 | struct vsp1_lif *lif = to_lif(subdev); | ||
147 | struct v4l2_mbus_framefmt *format; | ||
148 | |||
149 | /* Default to YUV if the requested format is not supported. */ | ||
150 | if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 && | ||
151 | fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32) | ||
152 | fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32; | ||
153 | |||
154 | format = vsp1_entity_get_pad_format(&lif->entity, fh, fmt->pad, | ||
155 | fmt->which); | ||
156 | |||
157 | if (fmt->pad == LIF_PAD_SOURCE) { | ||
158 | /* The LIF source format is always identical to its sink | ||
159 | * format. | ||
160 | */ | ||
161 | fmt->format = *format; | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | format->code = fmt->format.code; | ||
166 | format->width = clamp_t(unsigned int, fmt->format.width, | ||
167 | LIF_MIN_SIZE, LIF_MAX_SIZE); | ||
168 | format->height = clamp_t(unsigned int, fmt->format.height, | ||
169 | LIF_MIN_SIZE, LIF_MAX_SIZE); | ||
170 | format->field = V4L2_FIELD_NONE; | ||
171 | format->colorspace = V4L2_COLORSPACE_SRGB; | ||
172 | |||
173 | fmt->format = *format; | ||
174 | |||
175 | /* Propagate the format to the source pad. */ | ||
176 | format = vsp1_entity_get_pad_format(&lif->entity, fh, LIF_PAD_SOURCE, | ||
177 | fmt->which); | ||
178 | *format = fmt->format; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | /* ----------------------------------------------------------------------------- | ||
184 | * V4L2 Subdevice Operations | ||
185 | */ | ||
186 | |||
187 | static struct v4l2_subdev_video_ops lif_video_ops = { | ||
188 | .s_stream = lif_s_stream, | ||
189 | }; | ||
190 | |||
191 | static struct v4l2_subdev_pad_ops lif_pad_ops = { | ||
192 | .enum_mbus_code = lif_enum_mbus_code, | ||
193 | .enum_frame_size = lif_enum_frame_size, | ||
194 | .get_fmt = lif_get_format, | ||
195 | .set_fmt = lif_set_format, | ||
196 | }; | ||
197 | |||
198 | static struct v4l2_subdev_ops lif_ops = { | ||
199 | .video = &lif_video_ops, | ||
200 | .pad = &lif_pad_ops, | ||
201 | }; | ||
202 | |||
203 | /* ----------------------------------------------------------------------------- | ||
204 | * Initialization and Cleanup | ||
205 | */ | ||
206 | |||
207 | struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1) | ||
208 | { | ||
209 | struct v4l2_subdev *subdev; | ||
210 | struct vsp1_lif *lif; | ||
211 | int ret; | ||
212 | |||
213 | lif = devm_kzalloc(vsp1->dev, sizeof(*lif), GFP_KERNEL); | ||
214 | if (lif == NULL) | ||
215 | return ERR_PTR(-ENOMEM); | ||
216 | |||
217 | lif->entity.type = VSP1_ENTITY_LIF; | ||
218 | lif->entity.id = VI6_DPR_NODE_LIF; | ||
219 | |||
220 | ret = vsp1_entity_init(vsp1, &lif->entity, 2); | ||
221 | if (ret < 0) | ||
222 | return ERR_PTR(ret); | ||
223 | |||
224 | /* Initialize the V4L2 subdev. */ | ||
225 | subdev = &lif->entity.subdev; | ||
226 | v4l2_subdev_init(subdev, &lif_ops); | ||
227 | |||
228 | subdev->entity.ops = &vsp1_media_ops; | ||
229 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
230 | snprintf(subdev->name, sizeof(subdev->name), "%s lif", | ||
231 | dev_name(vsp1->dev)); | ||
232 | v4l2_set_subdevdata(subdev, lif); | ||
233 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
234 | |||
235 | vsp1_entity_init_formats(subdev, NULL); | ||
236 | |||
237 | return lif; | ||
238 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_lif.h b/drivers/media/platform/vsp1/vsp1_lif.h new file mode 100644 index 000000000000..89b93af56fdc --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_lif.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * vsp1_lif.h -- R-Car VSP1 LCD Controller Interface | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | #ifndef __VSP1_LIF_H__ | ||
14 | #define __VSP1_LIF_H__ | ||
15 | |||
16 | #include <media/media-entity.h> | ||
17 | #include <media/v4l2-subdev.h> | ||
18 | |||
19 | #include "vsp1_entity.h" | ||
20 | |||
21 | struct vsp1_device; | ||
22 | |||
23 | #define LIF_PAD_SINK 0 | ||
24 | #define LIF_PAD_SOURCE 1 | ||
25 | |||
26 | struct vsp1_lif { | ||
27 | struct vsp1_entity entity; | ||
28 | }; | ||
29 | |||
30 | static inline struct vsp1_lif *to_lif(struct v4l2_subdev *subdev) | ||
31 | { | ||
32 | return container_of(subdev, struct vsp1_lif, entity.subdev); | ||
33 | } | ||
34 | |||
35 | struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1); | ||
36 | |||
37 | #endif /* __VSP1_LIF_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h new file mode 100644 index 000000000000..1d3304f1365b --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_regs.h | |||
@@ -0,0 +1,581 @@ | |||
1 | /* | ||
2 | * vsp1_regs.h -- R-Car VSP1 Registers Definitions | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Electronics Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __VSP1_REGS_H__ | ||
14 | #define __VSP1_REGS_H__ | ||
15 | |||
16 | /* ----------------------------------------------------------------------------- | ||
17 | * General Control Registers | ||
18 | */ | ||
19 | |||
20 | #define VI6_CMD(n) (0x0000 + (n) * 4) | ||
21 | #define VI6_CMD_STRCMD (1 << 0) | ||
22 | |||
23 | #define VI6_CLK_DCSWT 0x0018 | ||
24 | #define VI6_CLK_DCSWT_CSTPW_MASK (0xff << 8) | ||
25 | #define VI6_CLK_DCSWT_CSTPW_SHIFT 8 | ||
26 | #define VI6_CLK_DCSWT_CSTRW_MASK (0xff << 0) | ||
27 | #define VI6_CLK_DCSWT_CSTRW_SHIFT 0 | ||
28 | |||
29 | #define VI6_SRESET 0x0028 | ||
30 | #define VI6_SRESET_SRTS(n) (1 << (n)) | ||
31 | |||
32 | #define VI6_STATUS 0x0038 | ||
33 | #define VI6_STATUS_SYS_ACT(n) (1 << ((n) + 8)) | ||
34 | |||
35 | #define VI6_WPF_IRQ_ENB(n) (0x0048 + (n) * 12) | ||
36 | #define VI6_WFP_IRQ_ENB_DFEE (1 << 1) | ||
37 | #define VI6_WFP_IRQ_ENB_FREE (1 << 0) | ||
38 | |||
39 | #define VI6_WPF_IRQ_STA(n) (0x004c + (n) * 12) | ||
40 | #define VI6_WFP_IRQ_STA_DFE (1 << 1) | ||
41 | #define VI6_WFP_IRQ_STA_FRE (1 << 0) | ||
42 | |||
43 | #define VI6_DISP_IRQ_ENB 0x0078 | ||
44 | #define VI6_DISP_IRQ_ENB_DSTE (1 << 8) | ||
45 | #define VI6_DISP_IRQ_ENB_MAEE (1 << 5) | ||
46 | #define VI6_DISP_IRQ_ENB_LNEE(n) (1 << ((n) + 4)) | ||
47 | |||
48 | #define VI6_DISP_IRQ_STA 0x007c | ||
49 | #define VI6_DISP_IRQ_STA_DSE (1 << 8) | ||
50 | #define VI6_DISP_IRQ_STA_MAE (1 << 5) | ||
51 | #define VI6_DISP_IRQ_STA_LNE(n) (1 << ((n) + 4)) | ||
52 | |||
53 | #define VI6_WPF_LINE_COUNT(n) (0x0084 + (n) * 4) | ||
54 | #define VI6_WPF_LINE_COUNT_MASK (0x1fffff << 0) | ||
55 | |||
56 | /* ----------------------------------------------------------------------------- | ||
57 | * Display List Control Registers | ||
58 | */ | ||
59 | |||
60 | #define VI6_DL_CTRL 0x0100 | ||
61 | #define VI6_DL_CTRL_AR_WAIT_MASK (0xffff << 16) | ||
62 | #define VI6_DL_CTRL_AR_WAIT_SHIFT 16 | ||
63 | #define VI6_DL_CTRL_DC2 (1 << 12) | ||
64 | #define VI6_DL_CTRL_DC1 (1 << 8) | ||
65 | #define VI6_DL_CTRL_DC0 (1 << 4) | ||
66 | #define VI6_DL_CTRL_CFM0 (1 << 2) | ||
67 | #define VI6_DL_CTRL_NH0 (1 << 1) | ||
68 | #define VI6_DL_CTRL_DLE (1 << 0) | ||
69 | |||
70 | #define VI6_DL_HDR_ADDR(n) (0x0104 + (n) * 4) | ||
71 | |||
72 | #define VI6_DL_SWAP 0x0114 | ||
73 | #define VI6_DL_SWAP_LWS (1 << 2) | ||
74 | #define VI6_DL_SWAP_WDS (1 << 1) | ||
75 | #define VI6_DL_SWAP_BTS (1 << 0) | ||
76 | |||
77 | #define VI6_DL_EXT_CTRL 0x011c | ||
78 | #define VI6_DL_EXT_CTRL_NWE (1 << 16) | ||
79 | #define VI6_DL_EXT_CTRL_POLINT_MASK (0x3f << 8) | ||
80 | #define VI6_DL_EXT_CTRL_POLINT_SHIFT 8 | ||
81 | #define VI6_DL_EXT_CTRL_DLPRI (1 << 5) | ||
82 | #define VI6_DL_EXT_CTRL_EXPRI (1 << 4) | ||
83 | #define VI6_DL_EXT_CTRL_EXT (1 << 0) | ||
84 | |||
85 | #define VI6_DL_BODY_SIZE 0x0120 | ||
86 | #define VI6_DL_BODY_SIZE_UPD (1 << 24) | ||
87 | #define VI6_DL_BODY_SIZE_BS_MASK (0x1ffff << 0) | ||
88 | #define VI6_DL_BODY_SIZE_BS_SHIFT 0 | ||
89 | |||
90 | /* ----------------------------------------------------------------------------- | ||
91 | * RPF Control Registers | ||
92 | */ | ||
93 | |||
94 | #define VI6_RPF_OFFSET 0x100 | ||
95 | |||
96 | #define VI6_RPF_SRC_BSIZE 0x0300 | ||
97 | #define VI6_RPF_SRC_BSIZE_BHSIZE_MASK (0x1fff << 16) | ||
98 | #define VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT 16 | ||
99 | #define VI6_RPF_SRC_BSIZE_BVSIZE_MASK (0x1fff << 0) | ||
100 | #define VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT 0 | ||
101 | |||
102 | #define VI6_RPF_SRC_ESIZE 0x0304 | ||
103 | #define VI6_RPF_SRC_ESIZE_EHSIZE_MASK (0x1fff << 16) | ||
104 | #define VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT 16 | ||
105 | #define VI6_RPF_SRC_ESIZE_EVSIZE_MASK (0x1fff << 0) | ||
106 | #define VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT 0 | ||
107 | |||
108 | #define VI6_RPF_INFMT 0x0308 | ||
109 | #define VI6_RPF_INFMT_VIR (1 << 28) | ||
110 | #define VI6_RPF_INFMT_CIPM (1 << 16) | ||
111 | #define VI6_RPF_INFMT_SPYCS (1 << 15) | ||
112 | #define VI6_RPF_INFMT_SPUVS (1 << 14) | ||
113 | #define VI6_RPF_INFMT_CEXT_ZERO (0 << 12) | ||
114 | #define VI6_RPF_INFMT_CEXT_EXT (1 << 12) | ||
115 | #define VI6_RPF_INFMT_CEXT_ONE (2 << 12) | ||
116 | #define VI6_RPF_INFMT_CEXT_MASK (3 << 12) | ||
117 | #define VI6_RPF_INFMT_RDTM_BT601 (0 << 9) | ||
118 | #define VI6_RPF_INFMT_RDTM_BT601_EXT (1 << 9) | ||
119 | #define VI6_RPF_INFMT_RDTM_BT709 (2 << 9) | ||
120 | #define VI6_RPF_INFMT_RDTM_BT709_EXT (3 << 9) | ||
121 | #define VI6_RPF_INFMT_RDTM_MASK (7 << 9) | ||
122 | #define VI6_RPF_INFMT_CSC (1 << 8) | ||
123 | #define VI6_RPF_INFMT_RDFMT_MASK (0x7f << 0) | ||
124 | #define VI6_RPF_INFMT_RDFMT_SHIFT 0 | ||
125 | |||
126 | #define VI6_RPF_DSWAP 0x030c | ||
127 | #define VI6_RPF_DSWAP_A_LLS (1 << 11) | ||
128 | #define VI6_RPF_DSWAP_A_LWS (1 << 10) | ||
129 | #define VI6_RPF_DSWAP_A_WDS (1 << 9) | ||
130 | #define VI6_RPF_DSWAP_A_BTS (1 << 8) | ||
131 | #define VI6_RPF_DSWAP_P_LLS (1 << 3) | ||
132 | #define VI6_RPF_DSWAP_P_LWS (1 << 2) | ||
133 | #define VI6_RPF_DSWAP_P_WDS (1 << 1) | ||
134 | #define VI6_RPF_DSWAP_P_BTS (1 << 0) | ||
135 | |||
136 | #define VI6_RPF_LOC 0x0310 | ||
137 | #define VI6_RPF_LOC_HCOORD_MASK (0x1fff << 16) | ||
138 | #define VI6_RPF_LOC_HCOORD_SHIFT 16 | ||
139 | #define VI6_RPF_LOC_VCOORD_MASK (0x1fff << 0) | ||
140 | #define VI6_RPF_LOC_VCOORD_SHIFT 0 | ||
141 | |||
142 | #define VI6_RPF_ALPH_SEL 0x0314 | ||
143 | #define VI6_RPF_ALPH_SEL_ASEL_PACKED (0 << 28) | ||
144 | #define VI6_RPF_ALPH_SEL_ASEL_8B_PLANE (1 << 28) | ||
145 | #define VI6_RPF_ALPH_SEL_ASEL_SELECT (2 << 28) | ||
146 | #define VI6_RPF_ALPH_SEL_ASEL_1B_PLANE (3 << 28) | ||
147 | #define VI6_RPF_ALPH_SEL_ASEL_FIXED (4 << 28) | ||
148 | #define VI6_RPF_ALPH_SEL_ASEL_MASK (7 << 28) | ||
149 | #define VI6_RPF_ALPH_SEL_ASEL_SHIFT 28 | ||
150 | #define VI6_RPF_ALPH_SEL_IROP_MASK (0xf << 24) | ||
151 | #define VI6_RPF_ALPH_SEL_IROP_SHIFT 24 | ||
152 | #define VI6_RPF_ALPH_SEL_BSEL (1 << 23) | ||
153 | #define VI6_RPF_ALPH_SEL_AEXT_ZERO (0 << 18) | ||
154 | #define VI6_RPF_ALPH_SEL_AEXT_EXT (1 << 18) | ||
155 | #define VI6_RPF_ALPH_SEL_AEXT_ONE (2 << 18) | ||
156 | #define VI6_RPF_ALPH_SEL_AEXT_MASK (3 << 18) | ||
157 | #define VI6_RPF_ALPH_SEL_ALPHA0_MASK (0xff << 8) | ||
158 | #define VI6_RPF_ALPH_SEL_ALPHA0_SHIFT 8 | ||
159 | #define VI6_RPF_ALPH_SEL_ALPHA1_MASK (0xff << 0) | ||
160 | #define VI6_RPF_ALPH_SEL_ALPHA1_SHIFT 0 | ||
161 | |||
162 | #define VI6_RPF_VRTCOL_SET 0x0318 | ||
163 | #define VI6_RPF_VRTCOL_SET_LAYA_MASK (0xff << 24) | ||
164 | #define VI6_RPF_VRTCOL_SET_LAYA_SHIFT 24 | ||
165 | #define VI6_RPF_VRTCOL_SET_LAYR_MASK (0xff << 16) | ||
166 | #define VI6_RPF_VRTCOL_SET_LAYR_SHIFT 16 | ||
167 | #define VI6_RPF_VRTCOL_SET_LAYG_MASK (0xff << 8) | ||
168 | #define VI6_RPF_VRTCOL_SET_LAYG_SHIFT 8 | ||
169 | #define VI6_RPF_VRTCOL_SET_LAYB_MASK (0xff << 0) | ||
170 | #define VI6_RPF_VRTCOL_SET_LAYB_SHIFT 0 | ||
171 | |||
172 | #define VI6_RPF_MSK_CTRL 0x031c | ||
173 | #define VI6_RPF_MSK_CTRL_MSK_EN (1 << 24) | ||
174 | #define VI6_RPF_MSK_CTRL_MGR_MASK (0xff << 16) | ||
175 | #define VI6_RPF_MSK_CTRL_MGR_SHIFT 16 | ||
176 | #define VI6_RPF_MSK_CTRL_MGG_MASK (0xff << 8) | ||
177 | #define VI6_RPF_MSK_CTRL_MGG_SHIFT 8 | ||
178 | #define VI6_RPF_MSK_CTRL_MGB_MASK (0xff << 0) | ||
179 | #define VI6_RPF_MSK_CTRL_MGB_SHIFT 0 | ||
180 | |||
181 | #define VI6_RPF_MSK_SET0 0x0320 | ||
182 | #define VI6_RPF_MSK_SET1 0x0324 | ||
183 | #define VI6_RPF_MSK_SET_MSA_MASK (0xff << 24) | ||
184 | #define VI6_RPF_MSK_SET_MSA_SHIFT 24 | ||
185 | #define VI6_RPF_MSK_SET_MSR_MASK (0xff << 16) | ||
186 | #define VI6_RPF_MSK_SET_MSR_SHIFT 16 | ||
187 | #define VI6_RPF_MSK_SET_MSG_MASK (0xff << 8) | ||
188 | #define VI6_RPF_MSK_SET_MSG_SHIFT 8 | ||
189 | #define VI6_RPF_MSK_SET_MSB_MASK (0xff << 0) | ||
190 | #define VI6_RPF_MSK_SET_MSB_SHIFT 0 | ||
191 | |||
192 | #define VI6_RPF_CKEY_CTRL 0x0328 | ||
193 | #define VI6_RPF_CKEY_CTRL_CV (1 << 4) | ||
194 | #define VI6_RPF_CKEY_CTRL_SAPE1 (1 << 1) | ||
195 | #define VI6_RPF_CKEY_CTRL_SAPE0 (1 << 0) | ||
196 | |||
197 | #define VI6_RPF_CKEY_SET0 0x032c | ||
198 | #define VI6_RPF_CKEY_SET1 0x0330 | ||
199 | #define VI6_RPF_CKEY_SET_AP_MASK (0xff << 24) | ||
200 | #define VI6_RPF_CKEY_SET_AP_SHIFT 24 | ||
201 | #define VI6_RPF_CKEY_SET_R_MASK (0xff << 16) | ||
202 | #define VI6_RPF_CKEY_SET_R_SHIFT 16 | ||
203 | #define VI6_RPF_CKEY_SET_GY_MASK (0xff << 8) | ||
204 | #define VI6_RPF_CKEY_SET_GY_SHIFT 8 | ||
205 | #define VI6_RPF_CKEY_SET_B_MASK (0xff << 0) | ||
206 | #define VI6_RPF_CKEY_SET_B_SHIFT 0 | ||
207 | |||
208 | #define VI6_RPF_SRCM_PSTRIDE 0x0334 | ||
209 | #define VI6_RPF_SRCM_PSTRIDE_Y_SHIFT 16 | ||
210 | #define VI6_RPF_SRCM_PSTRIDE_C_SHIFT 0 | ||
211 | |||
212 | #define VI6_RPF_SRCM_ASTRIDE 0x0338 | ||
213 | #define VI6_RPF_SRCM_PSTRIDE_A_SHIFT 0 | ||
214 | |||
215 | #define VI6_RPF_SRCM_ADDR_Y 0x033c | ||
216 | #define VI6_RPF_SRCM_ADDR_C0 0x0340 | ||
217 | #define VI6_RPF_SRCM_ADDR_C1 0x0344 | ||
218 | #define VI6_RPF_SRCM_ADDR_AI 0x0348 | ||
219 | |||
220 | /* ----------------------------------------------------------------------------- | ||
221 | * WPF Control Registers | ||
222 | */ | ||
223 | |||
224 | #define VI6_WPF_OFFSET 0x100 | ||
225 | |||
226 | #define VI6_WPF_SRCRPF 0x1000 | ||
227 | #define VI6_WPF_SRCRPF_VIRACT_DIS (0 << 28) | ||
228 | #define VI6_WPF_SRCRPF_VIRACT_SUB (1 << 28) | ||
229 | #define VI6_WPF_SRCRPF_VIRACT_MST (2 << 28) | ||
230 | #define VI6_WPF_SRCRPF_VIRACT_MASK (3 << 28) | ||
231 | #define VI6_WPF_SRCRPF_RPF_ACT_DIS(n) (0 << ((n) * 2)) | ||
232 | #define VI6_WPF_SRCRPF_RPF_ACT_SUB(n) (1 << ((n) * 2)) | ||
233 | #define VI6_WPF_SRCRPF_RPF_ACT_MST(n) (2 << ((n) * 2)) | ||
234 | #define VI6_WPF_SRCRPF_RPF_ACT_MASK(n) (3 << ((n) * 2)) | ||
235 | |||
236 | #define VI6_WPF_HSZCLIP 0x1004 | ||
237 | #define VI6_WPF_VSZCLIP 0x1008 | ||
238 | #define VI6_WPF_SZCLIP_EN (1 << 28) | ||
239 | #define VI6_WPF_SZCLIP_OFST_MASK (0xff << 16) | ||
240 | #define VI6_WPF_SZCLIP_OFST_SHIFT 16 | ||
241 | #define VI6_WPF_SZCLIP_SIZE_MASK (0x1fff << 0) | ||
242 | #define VI6_WPF_SZCLIP_SIZE_SHIFT 0 | ||
243 | |||
244 | #define VI6_WPF_OUTFMT 0x100c | ||
245 | #define VI6_WPF_OUTFMT_PDV_MASK (0xff << 24) | ||
246 | #define VI6_WPF_OUTFMT_PDV_SHIFT 24 | ||
247 | #define VI6_WPF_OUTFMT_PXA (1 << 23) | ||
248 | #define VI6_WPF_OUTFMT_FLP (1 << 16) | ||
249 | #define VI6_WPF_OUTFMT_SPYCS (1 << 15) | ||
250 | #define VI6_WPF_OUTFMT_SPUVS (1 << 14) | ||
251 | #define VI6_WPF_OUTFMT_DITH_DIS (0 << 12) | ||
252 | #define VI6_WPF_OUTFMT_DITH_EN (3 << 12) | ||
253 | #define VI6_WPF_OUTFMT_DITH_MASK (3 << 12) | ||
254 | #define VI6_WPF_OUTFMT_WRTM_BT601 (0 << 9) | ||
255 | #define VI6_WPF_OUTFMT_WRTM_BT601_EXT (1 << 9) | ||
256 | #define VI6_WPF_OUTFMT_WRTM_BT709 (2 << 9) | ||
257 | #define VI6_WPF_OUTFMT_WRTM_BT709_EXT (3 << 9) | ||
258 | #define VI6_WPF_OUTFMT_WRTM_MASK (7 << 9) | ||
259 | #define VI6_WPF_OUTFMT_CSC (1 << 8) | ||
260 | #define VI6_WPF_OUTFMT_WRFMT_MASK (0x7f << 0) | ||
261 | #define VI6_WPF_OUTFMT_WRFMT_SHIFT 0 | ||
262 | |||
263 | #define VI6_WPF_DSWAP 0x1010 | ||
264 | #define VI6_WPF_DSWAP_P_LLS (1 << 3) | ||
265 | #define VI6_WPF_DSWAP_P_LWS (1 << 2) | ||
266 | #define VI6_WPF_DSWAP_P_WDS (1 << 1) | ||
267 | #define VI6_WPF_DSWAP_P_BTS (1 << 0) | ||
268 | |||
269 | #define VI6_WPF_RNDCTRL 0x1014 | ||
270 | #define VI6_WPF_RNDCTRL_CBRM (1 << 28) | ||
271 | #define VI6_WPF_RNDCTRL_ABRM_TRUNC (0 << 24) | ||
272 | #define VI6_WPF_RNDCTRL_ABRM_ROUND (1 << 24) | ||
273 | #define VI6_WPF_RNDCTRL_ABRM_THRESH (2 << 24) | ||
274 | #define VI6_WPF_RNDCTRL_ABRM_MASK (3 << 24) | ||
275 | #define VI6_WPF_RNDCTRL_ATHRESH_MASK (0xff << 16) | ||
276 | #define VI6_WPF_RNDCTRL_ATHRESH_SHIFT 16 | ||
277 | #define VI6_WPF_RNDCTRL_CLMD_FULL (0 << 12) | ||
278 | #define VI6_WPF_RNDCTRL_CLMD_CLIP (1 << 12) | ||
279 | #define VI6_WPF_RNDCTRL_CLMD_EXT (2 << 12) | ||
280 | #define VI6_WPF_RNDCTRL_CLMD_MASK (3 << 12) | ||
281 | |||
282 | #define VI6_WPF_DSTM_STRIDE_Y 0x101c | ||
283 | #define VI6_WPF_DSTM_STRIDE_C 0x1020 | ||
284 | #define VI6_WPF_DSTM_ADDR_Y 0x1024 | ||
285 | #define VI6_WPF_DSTM_ADDR_C0 0x1028 | ||
286 | #define VI6_WPF_DSTM_ADDR_C1 0x102c | ||
287 | |||
288 | #define VI6_WPF_WRBCK_CTRL 0x1034 | ||
289 | #define VI6_WPF_WRBCK_CTRL_WBMD (1 << 0) | ||
290 | |||
291 | /* ----------------------------------------------------------------------------- | ||
292 | * DPR Control Registers | ||
293 | */ | ||
294 | |||
295 | #define VI6_DPR_RPF_ROUTE(n) (0x2000 + (n) * 4) | ||
296 | |||
297 | #define VI6_DPR_WPF_FPORCH(n) (0x2014 + (n) * 4) | ||
298 | #define VI6_DPR_WPF_FPORCH_FP_WPFN (5 << 8) | ||
299 | |||
300 | #define VI6_DPR_SRU_ROUTE 0x2024 | ||
301 | #define VI6_DPR_UDS_ROUTE(n) (0x2028 + (n) * 4) | ||
302 | #define VI6_DPR_LUT_ROUTE 0x203c | ||
303 | #define VI6_DPR_CLU_ROUTE 0x2040 | ||
304 | #define VI6_DPR_HST_ROUTE 0x2044 | ||
305 | #define VI6_DPR_HSI_ROUTE 0x2048 | ||
306 | #define VI6_DPR_BRU_ROUTE 0x204c | ||
307 | #define VI6_DPR_ROUTE_FXA_MASK (0xff << 8) | ||
308 | #define VI6_DPR_ROUTE_FXA_SHIFT 16 | ||
309 | #define VI6_DPR_ROUTE_FP_MASK (0xff << 8) | ||
310 | #define VI6_DPR_ROUTE_FP_SHIFT 8 | ||
311 | #define VI6_DPR_ROUTE_RT_MASK (0x3f << 0) | ||
312 | #define VI6_DPR_ROUTE_RT_SHIFT 0 | ||
313 | |||
314 | #define VI6_DPR_HGO_SMPPT 0x2050 | ||
315 | #define VI6_DPR_HGT_SMPPT 0x2054 | ||
316 | #define VI6_DPR_SMPPT_TGW_MASK (7 << 8) | ||
317 | #define VI6_DPR_SMPPT_TGW_SHIFT 8 | ||
318 | #define VI6_DPR_SMPPT_PT_MASK (0x3f << 0) | ||
319 | #define VI6_DPR_SMPPT_PT_SHIFT 0 | ||
320 | |||
321 | #define VI6_DPR_NODE_RPF(n) (n) | ||
322 | #define VI6_DPR_NODE_SRU 16 | ||
323 | #define VI6_DPR_NODE_UDS(n) (17 + (n)) | ||
324 | #define VI6_DPR_NODE_LUT 22 | ||
325 | #define VI6_DPR_NODE_BRU_IN(n) (23 + (n)) | ||
326 | #define VI6_DPR_NODE_BRU_OUT 27 | ||
327 | #define VI6_DPR_NODE_CLU 29 | ||
328 | #define VI6_DPR_NODE_HST 30 | ||
329 | #define VI6_DPR_NODE_HSI 31 | ||
330 | #define VI6_DPR_NODE_LIF 55 | ||
331 | #define VI6_DPR_NODE_WPF(n) (56 + (n)) | ||
332 | #define VI6_DPR_NODE_UNUSED 63 | ||
333 | |||
334 | /* ----------------------------------------------------------------------------- | ||
335 | * SRU Control Registers | ||
336 | */ | ||
337 | |||
338 | #define VI6_SRU_CTRL0 0x2200 | ||
339 | #define VI6_SRU_CTRL1 0x2204 | ||
340 | #define VI6_SRU_CTRL2 0x2208 | ||
341 | |||
342 | /* ----------------------------------------------------------------------------- | ||
343 | * UDS Control Registers | ||
344 | */ | ||
345 | |||
346 | #define VI6_UDS_OFFSET 0x100 | ||
347 | |||
348 | #define VI6_UDS_CTRL 0x2300 | ||
349 | #define VI6_UDS_CTRL_AMD (1 << 30) | ||
350 | #define VI6_UDS_CTRL_FMD (1 << 29) | ||
351 | #define VI6_UDS_CTRL_BLADV (1 << 28) | ||
352 | #define VI6_UDS_CTRL_AON (1 << 25) | ||
353 | #define VI6_UDS_CTRL_ATHON (1 << 24) | ||
354 | #define VI6_UDS_CTRL_BC (1 << 20) | ||
355 | #define VI6_UDS_CTRL_NE_A (1 << 19) | ||
356 | #define VI6_UDS_CTRL_NE_RCR (1 << 18) | ||
357 | #define VI6_UDS_CTRL_NE_GY (1 << 17) | ||
358 | #define VI6_UDS_CTRL_NE_BCB (1 << 16) | ||
359 | #define VI6_UDS_CTRL_TDIPC (1 << 1) | ||
360 | |||
361 | #define VI6_UDS_SCALE 0x2304 | ||
362 | #define VI6_UDS_SCALE_HMANT_MASK (0xf << 28) | ||
363 | #define VI6_UDS_SCALE_HMANT_SHIFT 28 | ||
364 | #define VI6_UDS_SCALE_HFRAC_MASK (0xfff << 16) | ||
365 | #define VI6_UDS_SCALE_HFRAC_SHIFT 16 | ||
366 | #define VI6_UDS_SCALE_VMANT_MASK (0xf << 12) | ||
367 | #define VI6_UDS_SCALE_VMANT_SHIFT 12 | ||
368 | #define VI6_UDS_SCALE_VFRAC_MASK (0xfff << 0) | ||
369 | #define VI6_UDS_SCALE_VFRAC_SHIFT 0 | ||
370 | |||
371 | #define VI6_UDS_ALPTH 0x2308 | ||
372 | #define VI6_UDS_ALPTH_TH1_MASK (0xff << 8) | ||
373 | #define VI6_UDS_ALPTH_TH1_SHIFT 8 | ||
374 | #define VI6_UDS_ALPTH_TH0_MASK (0xff << 0) | ||
375 | #define VI6_UDS_ALPTH_TH0_SHIFT 0 | ||
376 | |||
377 | #define VI6_UDS_ALPVAL 0x230c | ||
378 | #define VI6_UDS_ALPVAL_VAL2_MASK (0xff << 16) | ||
379 | #define VI6_UDS_ALPVAL_VAL2_SHIFT 16 | ||
380 | #define VI6_UDS_ALPVAL_VAL1_MASK (0xff << 8) | ||
381 | #define VI6_UDS_ALPVAL_VAL1_SHIFT 8 | ||
382 | #define VI6_UDS_ALPVAL_VAL0_MASK (0xff << 0) | ||
383 | #define VI6_UDS_ALPVAL_VAL0_SHIFT 0 | ||
384 | |||
385 | #define VI6_UDS_PASS_BWIDTH 0x2310 | ||
386 | #define VI6_UDS_PASS_BWIDTH_H_MASK (0x7f << 16) | ||
387 | #define VI6_UDS_PASS_BWIDTH_H_SHIFT 16 | ||
388 | #define VI6_UDS_PASS_BWIDTH_V_MASK (0x7f << 0) | ||
389 | #define VI6_UDS_PASS_BWIDTH_V_SHIFT 0 | ||
390 | |||
391 | #define VI6_UDS_IPC 0x2318 | ||
392 | #define VI6_UDS_IPC_FIELD (1 << 27) | ||
393 | #define VI6_UDS_IPC_VEDP_MASK (0xfff << 0) | ||
394 | #define VI6_UDS_IPC_VEDP_SHIFT 0 | ||
395 | |||
396 | #define VI6_UDS_CLIP_SIZE 0x2324 | ||
397 | #define VI6_UDS_CLIP_SIZE_HSIZE_MASK (0x1fff << 16) | ||
398 | #define VI6_UDS_CLIP_SIZE_HSIZE_SHIFT 16 | ||
399 | #define VI6_UDS_CLIP_SIZE_VSIZE_MASK (0x1fff << 0) | ||
400 | #define VI6_UDS_CLIP_SIZE_VSIZE_SHIFT 0 | ||
401 | |||
402 | #define VI6_UDS_FILL_COLOR 0x2328 | ||
403 | #define VI6_UDS_FILL_COLOR_RFILC_MASK (0xff << 16) | ||
404 | #define VI6_UDS_FILL_COLOR_RFILC_SHIFT 16 | ||
405 | #define VI6_UDS_FILL_COLOR_GFILC_MASK (0xff << 8) | ||
406 | #define VI6_UDS_FILL_COLOR_GFILC_SHIFT 8 | ||
407 | #define VI6_UDS_FILL_COLOR_BFILC_MASK (0xff << 0) | ||
408 | #define VI6_UDS_FILL_COLOR_BFILC_SHIFT 0 | ||
409 | |||
410 | /* ----------------------------------------------------------------------------- | ||
411 | * LUT Control Registers | ||
412 | */ | ||
413 | |||
414 | #define VI6_LUT_CTRL 0x2800 | ||
415 | |||
416 | /* ----------------------------------------------------------------------------- | ||
417 | * CLU Control Registers | ||
418 | */ | ||
419 | |||
420 | #define VI6_CLU_CTRL 0x2900 | ||
421 | |||
422 | /* ----------------------------------------------------------------------------- | ||
423 | * HST Control Registers | ||
424 | */ | ||
425 | |||
426 | #define VI6_HST_CTRL 0x2a00 | ||
427 | |||
428 | /* ----------------------------------------------------------------------------- | ||
429 | * HSI Control Registers | ||
430 | */ | ||
431 | |||
432 | #define VI6_HSI_CTRL 0x2b00 | ||
433 | |||
434 | /* ----------------------------------------------------------------------------- | ||
435 | * BRU Control Registers | ||
436 | */ | ||
437 | |||
438 | #define VI6_BRU_INCTRL 0x2c00 | ||
439 | #define VI6_BRU_VIRRPF_SIZE 0x2c04 | ||
440 | #define VI6_BRU_VIRRPF_LOC 0x2c08 | ||
441 | #define VI6_BRU_VIRRPF_COL 0x2c0c | ||
442 | #define VI6_BRU_CTRL(n) (0x2c10 + (n) * 8) | ||
443 | #define VI6_BRU_BLD(n) (0x2c14 + (n) * 8) | ||
444 | #define VI6_BRU_ROP 0x2c30 | ||
445 | |||
446 | /* ----------------------------------------------------------------------------- | ||
447 | * HGO Control Registers | ||
448 | */ | ||
449 | |||
450 | #define VI6_HGO_OFFSET 0x3000 | ||
451 | #define VI6_HGO_SIZE 0x3004 | ||
452 | #define VI6_HGO_MODE 0x3008 | ||
453 | #define VI6_HGO_LB_TH 0x300c | ||
454 | #define VI6_HGO_LBn_H(n) (0x3010 + (n) * 8) | ||
455 | #define VI6_HGO_LBn_V(n) (0x3014 + (n) * 8) | ||
456 | #define VI6_HGO_R_HISTO 0x3030 | ||
457 | #define VI6_HGO_R_MAXMIN 0x3130 | ||
458 | #define VI6_HGO_R_SUM 0x3134 | ||
459 | #define VI6_HGO_R_LB_DET 0x3138 | ||
460 | #define VI6_HGO_G_HISTO 0x3140 | ||
461 | #define VI6_HGO_G_MAXMIN 0x3240 | ||
462 | #define VI6_HGO_G_SUM 0x3244 | ||
463 | #define VI6_HGO_G_LB_DET 0x3248 | ||
464 | #define VI6_HGO_B_HISTO 0x3250 | ||
465 | #define VI6_HGO_B_MAXMIN 0x3350 | ||
466 | #define VI6_HGO_B_SUM 0x3354 | ||
467 | #define VI6_HGO_B_LB_DET 0x3358 | ||
468 | #define VI6_HGO_REGRST 0x33fc | ||
469 | |||
470 | /* ----------------------------------------------------------------------------- | ||
471 | * HGT Control Registers | ||
472 | */ | ||
473 | |||
474 | #define VI6_HGT_OFFSET 0x3400 | ||
475 | #define VI6_HGT_SIZE 0x3404 | ||
476 | #define VI6_HGT_MODE 0x3408 | ||
477 | #define VI6_HGT_HUE_AREA(n) (0x340c + (n) * 4) | ||
478 | #define VI6_HGT_LB_TH 0x3424 | ||
479 | #define VI6_HGT_LBn_H(n) (0x3438 + (n) * 8) | ||
480 | #define VI6_HGT_LBn_V(n) (0x342c + (n) * 8) | ||
481 | #define VI6_HGT_HISTO(m, n) (0x3450 + (m) * 128 + (n) * 4) | ||
482 | #define VI6_HGT_MAXMIN 0x3750 | ||
483 | #define VI6_HGT_SUM 0x3754 | ||
484 | #define VI6_HGT_LB_DET 0x3758 | ||
485 | #define VI6_HGT_REGRST 0x37fc | ||
486 | |||
487 | /* ----------------------------------------------------------------------------- | ||
488 | * LIF Control Registers | ||
489 | */ | ||
490 | |||
491 | #define VI6_LIF_CTRL 0x3b00 | ||
492 | #define VI6_LIF_CTRL_OBTH_MASK (0x7ff << 16) | ||
493 | #define VI6_LIF_CTRL_OBTH_SHIFT 16 | ||
494 | #define VI6_LIF_CTRL_CFMT (1 << 4) | ||
495 | #define VI6_LIF_CTRL_REQSEL (1 << 1) | ||
496 | #define VI6_LIF_CTRL_LIF_EN (1 << 0) | ||
497 | |||
498 | #define VI6_LIF_CSBTH 0x3b04 | ||
499 | #define VI6_LIF_CSBTH_HBTH_MASK (0x7ff << 16) | ||
500 | #define VI6_LIF_CSBTH_HBTH_SHIFT 16 | ||
501 | #define VI6_LIF_CSBTH_LBTH_MASK (0x7ff << 0) | ||
502 | #define VI6_LIF_CSBTH_LBTH_SHIFT 0 | ||
503 | |||
504 | /* ----------------------------------------------------------------------------- | ||
505 | * Security Control Registers | ||
506 | */ | ||
507 | |||
508 | #define VI6_SECURITY_CTRL0 0x3d00 | ||
509 | #define VI6_SECURITY_CTRL1 0x3d04 | ||
510 | |||
511 | /* ----------------------------------------------------------------------------- | ||
512 | * RPF CLUT Registers | ||
513 | */ | ||
514 | |||
515 | #define VI6_CLUT_TABLE 0x4000 | ||
516 | |||
517 | /* ----------------------------------------------------------------------------- | ||
518 | * 1D LUT Registers | ||
519 | */ | ||
520 | |||
521 | #define VI6_LUT_TABLE 0x7000 | ||
522 | |||
523 | /* ----------------------------------------------------------------------------- | ||
524 | * 3D LUT Registers | ||
525 | */ | ||
526 | |||
527 | #define VI6_CLU_ADDR 0x7400 | ||
528 | #define VI6_CLU_DATA 0x7404 | ||
529 | |||
530 | /* ----------------------------------------------------------------------------- | ||
531 | * Formats | ||
532 | */ | ||
533 | |||
534 | #define VI6_FMT_RGB_332 0x00 | ||
535 | #define VI6_FMT_XRGB_4444 0x01 | ||
536 | #define VI6_FMT_RGBX_4444 0x02 | ||
537 | #define VI6_FMT_XRGB_1555 0x04 | ||
538 | #define VI6_FMT_RGBX_5551 0x05 | ||
539 | #define VI6_FMT_RGB_565 0x06 | ||
540 | #define VI6_FMT_AXRGB_86666 0x07 | ||
541 | #define VI6_FMT_RGBXA_66668 0x08 | ||
542 | #define VI6_FMT_XRGBA_66668 0x09 | ||
543 | #define VI6_FMT_ARGBX_86666 0x0a | ||
544 | #define VI6_FMT_AXRXGXB_8262626 0x0b | ||
545 | #define VI6_FMT_XRXGXBA_2626268 0x0c | ||
546 | #define VI6_FMT_ARXGXBX_8626262 0x0d | ||
547 | #define VI6_FMT_RXGXBXA_6262628 0x0e | ||
548 | #define VI6_FMT_XRGB_6666 0x0f | ||
549 | #define VI6_FMT_RGBX_6666 0x10 | ||
550 | #define VI6_FMT_XRXGXB_262626 0x11 | ||
551 | #define VI6_FMT_RXGXBX_626262 0x12 | ||
552 | #define VI6_FMT_ARGB_8888 0x13 | ||
553 | #define VI6_FMT_RGBA_8888 0x14 | ||
554 | #define VI6_FMT_RGB_888 0x15 | ||
555 | #define VI6_FMT_XRGXGB_763763 0x16 | ||
556 | #define VI6_FMT_XXRGB_86666 0x17 | ||
557 | #define VI6_FMT_BGR_888 0x18 | ||
558 | #define VI6_FMT_ARGB_4444 0x19 | ||
559 | #define VI6_FMT_RGBA_4444 0x1a | ||
560 | #define VI6_FMT_ARGB_1555 0x1b | ||
561 | #define VI6_FMT_RGBA_5551 0x1c | ||
562 | #define VI6_FMT_ABGR_4444 0x1d | ||
563 | #define VI6_FMT_BGRA_4444 0x1e | ||
564 | #define VI6_FMT_ABGR_1555 0x1f | ||
565 | #define VI6_FMT_BGRA_5551 0x20 | ||
566 | #define VI6_FMT_XBXGXR_262626 0x21 | ||
567 | #define VI6_FMT_ABGR_8888 0x22 | ||
568 | #define VI6_FMT_XXRGB_88565 0x23 | ||
569 | |||
570 | #define VI6_FMT_Y_UV_444 0x40 | ||
571 | #define VI6_FMT_Y_UV_422 0x41 | ||
572 | #define VI6_FMT_Y_UV_420 0x42 | ||
573 | #define VI6_FMT_YUV_444 0x46 | ||
574 | #define VI6_FMT_YUYV_422 0x47 | ||
575 | #define VI6_FMT_YYUV_422 0x48 | ||
576 | #define VI6_FMT_YUV_420 0x49 | ||
577 | #define VI6_FMT_Y_U_V_444 0x4a | ||
578 | #define VI6_FMT_Y_U_V_422 0x4b | ||
579 | #define VI6_FMT_Y_U_V_420 0x4c | ||
580 | |||
581 | #endif /* __VSP1_REGS_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c new file mode 100644 index 000000000000..254871d3423e --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_rpf.c | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * vsp1_rpf.c -- R-Car VSP1 Read Pixel Formatter | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | |||
16 | #include <media/v4l2-subdev.h> | ||
17 | |||
18 | #include "vsp1.h" | ||
19 | #include "vsp1_rwpf.h" | ||
20 | #include "vsp1_video.h" | ||
21 | |||
22 | #define RPF_MAX_WIDTH 8190 | ||
23 | #define RPF_MAX_HEIGHT 8190 | ||
24 | |||
25 | /* ----------------------------------------------------------------------------- | ||
26 | * Device Access | ||
27 | */ | ||
28 | |||
29 | static inline u32 vsp1_rpf_read(struct vsp1_rwpf *rpf, u32 reg) | ||
30 | { | ||
31 | return vsp1_read(rpf->entity.vsp1, | ||
32 | reg + rpf->entity.index * VI6_RPF_OFFSET); | ||
33 | } | ||
34 | |||
35 | static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) | ||
36 | { | ||
37 | vsp1_write(rpf->entity.vsp1, | ||
38 | reg + rpf->entity.index * VI6_RPF_OFFSET, data); | ||
39 | } | ||
40 | |||
41 | /* ----------------------------------------------------------------------------- | ||
42 | * V4L2 Subdevice Core Operations | ||
43 | */ | ||
44 | |||
45 | static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) | ||
46 | { | ||
47 | struct vsp1_rwpf *rpf = to_rwpf(subdev); | ||
48 | const struct vsp1_format_info *fmtinfo = rpf->video.fmtinfo; | ||
49 | const struct v4l2_pix_format_mplane *format = &rpf->video.format; | ||
50 | u32 pstride; | ||
51 | u32 infmt; | ||
52 | |||
53 | if (!enable) | ||
54 | return 0; | ||
55 | |||
56 | /* Source size and stride. Cropping isn't supported yet. */ | ||
57 | vsp1_rpf_write(rpf, VI6_RPF_SRC_BSIZE, | ||
58 | (format->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | | ||
59 | (format->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); | ||
60 | vsp1_rpf_write(rpf, VI6_RPF_SRC_ESIZE, | ||
61 | (format->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | | ||
62 | (format->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); | ||
63 | |||
64 | pstride = format->plane_fmt[0].bytesperline | ||
65 | << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; | ||
66 | if (format->num_planes > 1) | ||
67 | pstride |= format->plane_fmt[1].bytesperline | ||
68 | << VI6_RPF_SRCM_PSTRIDE_C_SHIFT; | ||
69 | |||
70 | vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); | ||
71 | |||
72 | /* Format */ | ||
73 | infmt = VI6_RPF_INFMT_CIPM | ||
74 | | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT); | ||
75 | |||
76 | if (fmtinfo->swap_yc) | ||
77 | infmt |= VI6_RPF_INFMT_SPYCS; | ||
78 | if (fmtinfo->swap_uv) | ||
79 | infmt |= VI6_RPF_INFMT_SPUVS; | ||
80 | |||
81 | if (rpf->entity.formats[RWPF_PAD_SINK].code != | ||
82 | rpf->entity.formats[RWPF_PAD_SOURCE].code) | ||
83 | infmt |= VI6_RPF_INFMT_CSC; | ||
84 | |||
85 | vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt); | ||
86 | vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap); | ||
87 | |||
88 | /* Output location. Composing isn't supported yet. */ | ||
89 | vsp1_rpf_write(rpf, VI6_RPF_LOC, 0); | ||
90 | |||
91 | /* Disable alpha, mask and color key. Set the alpha channel to a fixed | ||
92 | * value of 255. | ||
93 | */ | ||
94 | vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_FIXED); | ||
95 | vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, | ||
96 | 255 << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); | ||
97 | vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); | ||
98 | vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | /* ----------------------------------------------------------------------------- | ||
104 | * V4L2 Subdevice Operations | ||
105 | */ | ||
106 | |||
107 | static struct v4l2_subdev_video_ops rpf_video_ops = { | ||
108 | .s_stream = rpf_s_stream, | ||
109 | }; | ||
110 | |||
111 | static struct v4l2_subdev_pad_ops rpf_pad_ops = { | ||
112 | .enum_mbus_code = vsp1_rwpf_enum_mbus_code, | ||
113 | .enum_frame_size = vsp1_rwpf_enum_frame_size, | ||
114 | .get_fmt = vsp1_rwpf_get_format, | ||
115 | .set_fmt = vsp1_rwpf_set_format, | ||
116 | }; | ||
117 | |||
118 | static struct v4l2_subdev_ops rpf_ops = { | ||
119 | .video = &rpf_video_ops, | ||
120 | .pad = &rpf_pad_ops, | ||
121 | }; | ||
122 | |||
123 | /* ----------------------------------------------------------------------------- | ||
124 | * Video Device Operations | ||
125 | */ | ||
126 | |||
127 | static void rpf_vdev_queue(struct vsp1_video *video, | ||
128 | struct vsp1_video_buffer *buf) | ||
129 | { | ||
130 | struct vsp1_rwpf *rpf = container_of(video, struct vsp1_rwpf, video); | ||
131 | |||
132 | vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, buf->addr[0]); | ||
133 | if (buf->buf.num_planes > 1) | ||
134 | vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, buf->addr[1]); | ||
135 | if (buf->buf.num_planes > 2) | ||
136 | vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, buf->addr[2]); | ||
137 | } | ||
138 | |||
139 | static const struct vsp1_video_operations rpf_vdev_ops = { | ||
140 | .queue = rpf_vdev_queue, | ||
141 | }; | ||
142 | |||
143 | /* ----------------------------------------------------------------------------- | ||
144 | * Initialization and Cleanup | ||
145 | */ | ||
146 | |||
147 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) | ||
148 | { | ||
149 | struct v4l2_subdev *subdev; | ||
150 | struct vsp1_video *video; | ||
151 | struct vsp1_rwpf *rpf; | ||
152 | int ret; | ||
153 | |||
154 | rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL); | ||
155 | if (rpf == NULL) | ||
156 | return ERR_PTR(-ENOMEM); | ||
157 | |||
158 | rpf->max_width = RPF_MAX_WIDTH; | ||
159 | rpf->max_height = RPF_MAX_HEIGHT; | ||
160 | |||
161 | rpf->entity.type = VSP1_ENTITY_RPF; | ||
162 | rpf->entity.index = index; | ||
163 | rpf->entity.id = VI6_DPR_NODE_RPF(index); | ||
164 | |||
165 | ret = vsp1_entity_init(vsp1, &rpf->entity, 2); | ||
166 | if (ret < 0) | ||
167 | return ERR_PTR(ret); | ||
168 | |||
169 | /* Initialize the V4L2 subdev. */ | ||
170 | subdev = &rpf->entity.subdev; | ||
171 | v4l2_subdev_init(subdev, &rpf_ops); | ||
172 | |||
173 | subdev->entity.ops = &vsp1_media_ops; | ||
174 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
175 | snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u", | ||
176 | dev_name(vsp1->dev), index); | ||
177 | v4l2_set_subdevdata(subdev, rpf); | ||
178 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
179 | |||
180 | vsp1_entity_init_formats(subdev, NULL); | ||
181 | |||
182 | /* Initialize the video device. */ | ||
183 | video = &rpf->video; | ||
184 | |||
185 | video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | ||
186 | video->vsp1 = vsp1; | ||
187 | video->ops = &rpf_vdev_ops; | ||
188 | |||
189 | ret = vsp1_video_init(video, &rpf->entity); | ||
190 | if (ret < 0) | ||
191 | goto error_video; | ||
192 | |||
193 | /* Connect the video device to the RPF. */ | ||
194 | ret = media_entity_create_link(&rpf->video.video.entity, 0, | ||
195 | &rpf->entity.subdev.entity, | ||
196 | RWPF_PAD_SINK, | ||
197 | MEDIA_LNK_FL_ENABLED | | ||
198 | MEDIA_LNK_FL_IMMUTABLE); | ||
199 | if (ret < 0) | ||
200 | goto error_link; | ||
201 | |||
202 | return rpf; | ||
203 | |||
204 | error_link: | ||
205 | vsp1_video_cleanup(video); | ||
206 | error_video: | ||
207 | media_entity_cleanup(&rpf->entity.subdev.entity); | ||
208 | return ERR_PTR(ret); | ||
209 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c new file mode 100644 index 000000000000..9752d5516ceb --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * vsp1_rwpf.c -- R-Car VSP1 Read and Write Pixel Formatters | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <media/v4l2-subdev.h> | ||
15 | |||
16 | #include "vsp1.h" | ||
17 | #include "vsp1_rwpf.h" | ||
18 | #include "vsp1_video.h" | ||
19 | |||
20 | #define RWPF_MIN_WIDTH 1 | ||
21 | #define RWPF_MIN_HEIGHT 1 | ||
22 | |||
23 | /* ----------------------------------------------------------------------------- | ||
24 | * V4L2 Subdevice Pad Operations | ||
25 | */ | ||
26 | |||
27 | int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, | ||
28 | struct v4l2_subdev_fh *fh, | ||
29 | struct v4l2_subdev_mbus_code_enum *code) | ||
30 | { | ||
31 | static const unsigned int codes[] = { | ||
32 | V4L2_MBUS_FMT_ARGB8888_1X32, | ||
33 | V4L2_MBUS_FMT_AYUV8_1X32, | ||
34 | }; | ||
35 | |||
36 | if (code->index >= ARRAY_SIZE(codes)) | ||
37 | return -EINVAL; | ||
38 | |||
39 | code->code = codes[code->index]; | ||
40 | |||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, | ||
45 | struct v4l2_subdev_fh *fh, | ||
46 | struct v4l2_subdev_frame_size_enum *fse) | ||
47 | { | ||
48 | struct vsp1_rwpf *rwpf = to_rwpf(subdev); | ||
49 | struct v4l2_mbus_framefmt *format; | ||
50 | |||
51 | format = v4l2_subdev_get_try_format(fh, fse->pad); | ||
52 | |||
53 | if (fse->index || fse->code != format->code) | ||
54 | return -EINVAL; | ||
55 | |||
56 | if (fse->pad == RWPF_PAD_SINK) { | ||
57 | fse->min_width = RWPF_MIN_WIDTH; | ||
58 | fse->max_width = rwpf->max_width; | ||
59 | fse->min_height = RWPF_MIN_HEIGHT; | ||
60 | fse->max_height = rwpf->max_height; | ||
61 | } else { | ||
62 | /* The size on the source pad are fixed and always identical to | ||
63 | * the size on the sink pad. | ||
64 | */ | ||
65 | fse->min_width = format->width; | ||
66 | fse->max_width = format->width; | ||
67 | fse->min_height = format->height; | ||
68 | fse->max_height = format->height; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
75 | struct v4l2_subdev_format *fmt) | ||
76 | { | ||
77 | struct vsp1_rwpf *rwpf = to_rwpf(subdev); | ||
78 | |||
79 | fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad, | ||
80 | fmt->which); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
86 | struct v4l2_subdev_format *fmt) | ||
87 | { | ||
88 | struct vsp1_rwpf *rwpf = to_rwpf(subdev); | ||
89 | struct v4l2_mbus_framefmt *format; | ||
90 | |||
91 | /* Default to YUV if the requested format is not supported. */ | ||
92 | if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 && | ||
93 | fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32) | ||
94 | fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32; | ||
95 | |||
96 | format = vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad, | ||
97 | fmt->which); | ||
98 | |||
99 | if (fmt->pad == RWPF_PAD_SOURCE) { | ||
100 | /* The RWPF performs format conversion but can't scale, only the | ||
101 | * format code can be changed on the source pad. | ||
102 | */ | ||
103 | format->code = fmt->format.code; | ||
104 | fmt->format = *format; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | format->code = fmt->format.code; | ||
109 | format->width = clamp_t(unsigned int, fmt->format.width, | ||
110 | RWPF_MIN_WIDTH, rwpf->max_width); | ||
111 | format->height = clamp_t(unsigned int, fmt->format.height, | ||
112 | RWPF_MIN_HEIGHT, rwpf->max_height); | ||
113 | format->field = V4L2_FIELD_NONE; | ||
114 | format->colorspace = V4L2_COLORSPACE_SRGB; | ||
115 | |||
116 | fmt->format = *format; | ||
117 | |||
118 | /* Propagate the format to the source pad. */ | ||
119 | format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SOURCE, | ||
120 | fmt->which); | ||
121 | *format = fmt->format; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h new file mode 100644 index 000000000000..c182d85f36b3 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * vsp1_rwpf.h -- R-Car VSP1 Read and Write Pixel Formatters | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | #ifndef __VSP1_RWPF_H__ | ||
14 | #define __VSP1_RWPF_H__ | ||
15 | |||
16 | #include <media/media-entity.h> | ||
17 | #include <media/v4l2-subdev.h> | ||
18 | |||
19 | #include "vsp1.h" | ||
20 | #include "vsp1_entity.h" | ||
21 | #include "vsp1_video.h" | ||
22 | |||
23 | #define RWPF_PAD_SINK 0 | ||
24 | #define RWPF_PAD_SOURCE 1 | ||
25 | |||
26 | struct vsp1_rwpf { | ||
27 | struct vsp1_entity entity; | ||
28 | struct vsp1_video video; | ||
29 | |||
30 | unsigned int max_width; | ||
31 | unsigned int max_height; | ||
32 | }; | ||
33 | |||
34 | static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) | ||
35 | { | ||
36 | return container_of(subdev, struct vsp1_rwpf, entity.subdev); | ||
37 | } | ||
38 | |||
39 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); | ||
40 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); | ||
41 | |||
42 | int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, | ||
43 | struct v4l2_subdev_fh *fh, | ||
44 | struct v4l2_subdev_mbus_code_enum *code); | ||
45 | int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, | ||
46 | struct v4l2_subdev_fh *fh, | ||
47 | struct v4l2_subdev_frame_size_enum *fse); | ||
48 | int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
49 | struct v4l2_subdev_format *fmt); | ||
50 | int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
51 | struct v4l2_subdev_format *fmt); | ||
52 | |||
53 | #endif /* __VSP1_RWPF_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c new file mode 100644 index 000000000000..0e50b37f060d --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uds.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | * vsp1_uds.c -- R-Car VSP1 Up and Down Scaler | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/gfp.h> | ||
16 | |||
17 | #include <media/v4l2-subdev.h> | ||
18 | |||
19 | #include "vsp1.h" | ||
20 | #include "vsp1_uds.h" | ||
21 | |||
22 | #define UDS_MIN_SIZE 4U | ||
23 | #define UDS_MAX_SIZE 8190U | ||
24 | |||
25 | #define UDS_MIN_FACTOR 0x0100 | ||
26 | #define UDS_MAX_FACTOR 0xffff | ||
27 | |||
28 | /* ----------------------------------------------------------------------------- | ||
29 | * Device Access | ||
30 | */ | ||
31 | |||
32 | static inline u32 vsp1_uds_read(struct vsp1_uds *uds, u32 reg) | ||
33 | { | ||
34 | return vsp1_read(uds->entity.vsp1, | ||
35 | reg + uds->entity.index * VI6_UDS_OFFSET); | ||
36 | } | ||
37 | |||
38 | static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data) | ||
39 | { | ||
40 | vsp1_write(uds->entity.vsp1, | ||
41 | reg + uds->entity.index * VI6_UDS_OFFSET, data); | ||
42 | } | ||
43 | |||
44 | /* ----------------------------------------------------------------------------- | ||
45 | * Scaling Computation | ||
46 | */ | ||
47 | |||
48 | /* | ||
49 | * uds_output_size - Return the output size for an input size and scaling ratio | ||
50 | * @input: input size in pixels | ||
51 | * @ratio: scaling ratio in U4.12 fixed-point format | ||
52 | */ | ||
53 | static unsigned int uds_output_size(unsigned int input, unsigned int ratio) | ||
54 | { | ||
55 | if (ratio > 4096) { | ||
56 | /* Down-scaling */ | ||
57 | unsigned int mp; | ||
58 | |||
59 | mp = ratio / 4096; | ||
60 | mp = mp < 4 ? 1 : (mp < 8 ? 2 : 4); | ||
61 | |||
62 | return (input - 1) / mp * mp * 4096 / ratio + 1; | ||
63 | } else { | ||
64 | /* Up-scaling */ | ||
65 | return (input - 1) * 4096 / ratio + 1; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * uds_output_limits - Return the min and max output sizes for an input size | ||
71 | * @input: input size in pixels | ||
72 | * @minimum: minimum output size (returned) | ||
73 | * @maximum: maximum output size (returned) | ||
74 | */ | ||
75 | static void uds_output_limits(unsigned int input, | ||
76 | unsigned int *minimum, unsigned int *maximum) | ||
77 | { | ||
78 | *minimum = max(uds_output_size(input, UDS_MAX_FACTOR), UDS_MIN_SIZE); | ||
79 | *maximum = min(uds_output_size(input, UDS_MIN_FACTOR), UDS_MAX_SIZE); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * uds_passband_width - Return the passband filter width for a scaling ratio | ||
84 | * @ratio: scaling ratio in U4.12 fixed-point format | ||
85 | */ | ||
86 | static unsigned int uds_passband_width(unsigned int ratio) | ||
87 | { | ||
88 | if (ratio >= 4096) { | ||
89 | /* Down-scaling */ | ||
90 | unsigned int mp; | ||
91 | |||
92 | mp = ratio / 4096; | ||
93 | mp = mp < 4 ? 1 : (mp < 8 ? 2 : 4); | ||
94 | |||
95 | return 64 * 4096 * mp / ratio; | ||
96 | } else { | ||
97 | /* Up-scaling */ | ||
98 | return 64; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | static unsigned int uds_compute_ratio(unsigned int input, unsigned int output) | ||
103 | { | ||
104 | /* TODO: This is an approximation that will need to be refined. */ | ||
105 | return (input - 1) * 4096 / (output - 1); | ||
106 | } | ||
107 | |||
108 | static void uds_compute_ratios(struct vsp1_uds *uds) | ||
109 | { | ||
110 | struct v4l2_mbus_framefmt *input = &uds->entity.formats[UDS_PAD_SINK]; | ||
111 | struct v4l2_mbus_framefmt *output = | ||
112 | &uds->entity.formats[UDS_PAD_SOURCE]; | ||
113 | |||
114 | uds->hscale = uds_compute_ratio(input->width, output->width); | ||
115 | uds->vscale = uds_compute_ratio(input->height, output->height); | ||
116 | |||
117 | dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", | ||
118 | uds->hscale, uds->vscale); | ||
119 | } | ||
120 | |||
121 | /* ----------------------------------------------------------------------------- | ||
122 | * V4L2 Subdevice Core Operations | ||
123 | */ | ||
124 | |||
125 | static int uds_s_stream(struct v4l2_subdev *subdev, int enable) | ||
126 | { | ||
127 | const struct v4l2_mbus_framefmt *format; | ||
128 | struct vsp1_uds *uds = to_uds(subdev); | ||
129 | |||
130 | if (!enable) | ||
131 | return 0; | ||
132 | |||
133 | /* Enable multi-tap scaling. */ | ||
134 | vsp1_uds_write(uds, VI6_UDS_CTRL, VI6_UDS_CTRL_BC); | ||
135 | |||
136 | vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH, | ||
137 | (uds_passband_width(uds->hscale) | ||
138 | << VI6_UDS_PASS_BWIDTH_H_SHIFT) | | ||
139 | (uds_passband_width(uds->vscale) | ||
140 | << VI6_UDS_PASS_BWIDTH_V_SHIFT)); | ||
141 | |||
142 | |||
143 | /* Set the scaling ratios and the output size. */ | ||
144 | format = &uds->entity.formats[UDS_PAD_SOURCE]; | ||
145 | |||
146 | vsp1_uds_write(uds, VI6_UDS_SCALE, | ||
147 | (uds->hscale << VI6_UDS_SCALE_HFRAC_SHIFT) | | ||
148 | (uds->vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); | ||
149 | vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE, | ||
150 | (format->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | | ||
151 | (format->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | /* ----------------------------------------------------------------------------- | ||
157 | * V4L2 Subdevice Pad Operations | ||
158 | */ | ||
159 | |||
160 | static int uds_enum_mbus_code(struct v4l2_subdev *subdev, | ||
161 | struct v4l2_subdev_fh *fh, | ||
162 | struct v4l2_subdev_mbus_code_enum *code) | ||
163 | { | ||
164 | static const unsigned int codes[] = { | ||
165 | V4L2_MBUS_FMT_ARGB8888_1X32, | ||
166 | V4L2_MBUS_FMT_AYUV8_1X32, | ||
167 | }; | ||
168 | |||
169 | if (code->pad == UDS_PAD_SINK) { | ||
170 | if (code->index >= ARRAY_SIZE(codes)) | ||
171 | return -EINVAL; | ||
172 | |||
173 | code->code = codes[code->index]; | ||
174 | } else { | ||
175 | struct v4l2_mbus_framefmt *format; | ||
176 | |||
177 | /* The UDS can't perform format conversion, the sink format is | ||
178 | * always identical to the source format. | ||
179 | */ | ||
180 | if (code->index) | ||
181 | return -EINVAL; | ||
182 | |||
183 | format = v4l2_subdev_get_try_format(fh, UDS_PAD_SINK); | ||
184 | code->code = format->code; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int uds_enum_frame_size(struct v4l2_subdev *subdev, | ||
191 | struct v4l2_subdev_fh *fh, | ||
192 | struct v4l2_subdev_frame_size_enum *fse) | ||
193 | { | ||
194 | struct v4l2_mbus_framefmt *format; | ||
195 | |||
196 | format = v4l2_subdev_get_try_format(fh, UDS_PAD_SINK); | ||
197 | |||
198 | if (fse->index || fse->code != format->code) | ||
199 | return -EINVAL; | ||
200 | |||
201 | if (fse->pad == UDS_PAD_SINK) { | ||
202 | fse->min_width = UDS_MIN_SIZE; | ||
203 | fse->max_width = UDS_MAX_SIZE; | ||
204 | fse->min_height = UDS_MIN_SIZE; | ||
205 | fse->max_height = UDS_MAX_SIZE; | ||
206 | } else { | ||
207 | uds_output_limits(format->width, &fse->min_width, | ||
208 | &fse->max_width); | ||
209 | uds_output_limits(format->height, &fse->min_height, | ||
210 | &fse->max_height); | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
217 | struct v4l2_subdev_format *fmt) | ||
218 | { | ||
219 | struct vsp1_uds *uds = to_uds(subdev); | ||
220 | |||
221 | fmt->format = *vsp1_entity_get_pad_format(&uds->entity, fh, fmt->pad, | ||
222 | fmt->which); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_fh *fh, | ||
228 | unsigned int pad, struct v4l2_mbus_framefmt *fmt, | ||
229 | enum v4l2_subdev_format_whence which) | ||
230 | { | ||
231 | struct v4l2_mbus_framefmt *format; | ||
232 | unsigned int minimum; | ||
233 | unsigned int maximum; | ||
234 | |||
235 | switch (pad) { | ||
236 | case UDS_PAD_SINK: | ||
237 | /* Default to YUV if the requested format is not supported. */ | ||
238 | if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 && | ||
239 | fmt->code != V4L2_MBUS_FMT_AYUV8_1X32) | ||
240 | fmt->code = V4L2_MBUS_FMT_AYUV8_1X32; | ||
241 | |||
242 | fmt->width = clamp(fmt->width, UDS_MIN_SIZE, UDS_MAX_SIZE); | ||
243 | fmt->height = clamp(fmt->height, UDS_MIN_SIZE, UDS_MAX_SIZE); | ||
244 | break; | ||
245 | |||
246 | case UDS_PAD_SOURCE: | ||
247 | /* The UDS scales but can't perform format conversion. */ | ||
248 | format = vsp1_entity_get_pad_format(&uds->entity, fh, | ||
249 | UDS_PAD_SINK, which); | ||
250 | fmt->code = format->code; | ||
251 | |||
252 | uds_output_limits(format->width, &minimum, &maximum); | ||
253 | fmt->width = clamp(fmt->width, minimum, maximum); | ||
254 | uds_output_limits(format->height, &minimum, &maximum); | ||
255 | fmt->height = clamp(fmt->height, minimum, maximum); | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | fmt->field = V4L2_FIELD_NONE; | ||
260 | fmt->colorspace = V4L2_COLORSPACE_SRGB; | ||
261 | } | ||
262 | |||
263 | static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
264 | struct v4l2_subdev_format *fmt) | ||
265 | { | ||
266 | struct vsp1_uds *uds = to_uds(subdev); | ||
267 | struct v4l2_mbus_framefmt *format; | ||
268 | |||
269 | uds_try_format(uds, fh, fmt->pad, &fmt->format, fmt->which); | ||
270 | |||
271 | format = vsp1_entity_get_pad_format(&uds->entity, fh, fmt->pad, | ||
272 | fmt->which); | ||
273 | *format = fmt->format; | ||
274 | |||
275 | if (fmt->pad == UDS_PAD_SINK) { | ||
276 | /* Propagate the format to the source pad. */ | ||
277 | format = vsp1_entity_get_pad_format(&uds->entity, fh, | ||
278 | UDS_PAD_SOURCE, fmt->which); | ||
279 | *format = fmt->format; | ||
280 | |||
281 | uds_try_format(uds, fh, UDS_PAD_SOURCE, format, fmt->which); | ||
282 | } | ||
283 | |||
284 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) | ||
285 | uds_compute_ratios(uds); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | /* ----------------------------------------------------------------------------- | ||
291 | * V4L2 Subdevice Operations | ||
292 | */ | ||
293 | |||
294 | static struct v4l2_subdev_video_ops uds_video_ops = { | ||
295 | .s_stream = uds_s_stream, | ||
296 | }; | ||
297 | |||
298 | static struct v4l2_subdev_pad_ops uds_pad_ops = { | ||
299 | .enum_mbus_code = uds_enum_mbus_code, | ||
300 | .enum_frame_size = uds_enum_frame_size, | ||
301 | .get_fmt = uds_get_format, | ||
302 | .set_fmt = uds_set_format, | ||
303 | }; | ||
304 | |||
305 | static struct v4l2_subdev_ops uds_ops = { | ||
306 | .video = &uds_video_ops, | ||
307 | .pad = &uds_pad_ops, | ||
308 | }; | ||
309 | |||
310 | /* ----------------------------------------------------------------------------- | ||
311 | * Initialization and Cleanup | ||
312 | */ | ||
313 | |||
314 | struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index) | ||
315 | { | ||
316 | struct v4l2_subdev *subdev; | ||
317 | struct vsp1_uds *uds; | ||
318 | int ret; | ||
319 | |||
320 | uds = devm_kzalloc(vsp1->dev, sizeof(*uds), GFP_KERNEL); | ||
321 | if (uds == NULL) | ||
322 | return ERR_PTR(-ENOMEM); | ||
323 | |||
324 | uds->entity.type = VSP1_ENTITY_UDS; | ||
325 | uds->entity.index = index; | ||
326 | uds->entity.id = VI6_DPR_NODE_UDS(index); | ||
327 | |||
328 | ret = vsp1_entity_init(vsp1, &uds->entity, 2); | ||
329 | if (ret < 0) | ||
330 | return ERR_PTR(ret); | ||
331 | |||
332 | /* Initialize the V4L2 subdev. */ | ||
333 | subdev = &uds->entity.subdev; | ||
334 | v4l2_subdev_init(subdev, &uds_ops); | ||
335 | |||
336 | subdev->entity.ops = &vsp1_media_ops; | ||
337 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
338 | snprintf(subdev->name, sizeof(subdev->name), "%s uds.%u", | ||
339 | dev_name(vsp1->dev), index); | ||
340 | v4l2_set_subdevdata(subdev, uds); | ||
341 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
342 | |||
343 | vsp1_entity_init_formats(subdev, NULL); | ||
344 | |||
345 | return uds; | ||
346 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h new file mode 100644 index 000000000000..972a285abdb9 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uds.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * vsp1_uds.h -- R-Car VSP1 Up and Down Scaler | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | #ifndef __VSP1_UDS_H__ | ||
14 | #define __VSP1_UDS_H__ | ||
15 | |||
16 | #include <media/media-entity.h> | ||
17 | #include <media/v4l2-subdev.h> | ||
18 | |||
19 | #include "vsp1_entity.h" | ||
20 | |||
21 | struct vsp1_device; | ||
22 | |||
23 | #define UDS_PAD_SINK 0 | ||
24 | #define UDS_PAD_SOURCE 1 | ||
25 | |||
26 | struct vsp1_uds { | ||
27 | struct vsp1_entity entity; | ||
28 | |||
29 | unsigned int hscale; | ||
30 | unsigned int vscale; | ||
31 | }; | ||
32 | |||
33 | static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev) | ||
34 | { | ||
35 | return container_of(subdev, struct vsp1_uds, entity.subdev); | ||
36 | } | ||
37 | |||
38 | struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index); | ||
39 | |||
40 | #endif /* __VSP1_UDS_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c new file mode 100644 index 000000000000..714c53ef6c11 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_video.c | |||
@@ -0,0 +1,1069 @@ | |||
1 | /* | ||
2 | * vsp1_video.c -- R-Car VSP1 Video Node | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/list.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/mutex.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/v4l2-mediabus.h> | ||
20 | #include <linux/videodev2.h> | ||
21 | |||
22 | #include <media/media-entity.h> | ||
23 | #include <media/v4l2-dev.h> | ||
24 | #include <media/v4l2-fh.h> | ||
25 | #include <media/v4l2-ioctl.h> | ||
26 | #include <media/v4l2-subdev.h> | ||
27 | #include <media/videobuf2-core.h> | ||
28 | #include <media/videobuf2-dma-contig.h> | ||
29 | |||
30 | #include "vsp1.h" | ||
31 | #include "vsp1_entity.h" | ||
32 | #include "vsp1_rwpf.h" | ||
33 | #include "vsp1_video.h" | ||
34 | |||
35 | #define VSP1_VIDEO_DEF_FORMAT V4L2_PIX_FMT_YUYV | ||
36 | #define VSP1_VIDEO_DEF_WIDTH 1024 | ||
37 | #define VSP1_VIDEO_DEF_HEIGHT 768 | ||
38 | |||
39 | #define VSP1_VIDEO_MIN_WIDTH 2U | ||
40 | #define VSP1_VIDEO_MAX_WIDTH 8190U | ||
41 | #define VSP1_VIDEO_MIN_HEIGHT 2U | ||
42 | #define VSP1_VIDEO_MAX_HEIGHT 8190U | ||
43 | |||
44 | /* ----------------------------------------------------------------------------- | ||
45 | * Helper functions | ||
46 | */ | ||
47 | |||
48 | static const struct vsp1_format_info vsp1_video_formats[] = { | ||
49 | { V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
50 | VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
51 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
52 | 1, { 8, 0, 0 }, false, false, 1, 1 }, | ||
53 | { V4L2_PIX_FMT_RGB444, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
54 | VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
55 | VI6_RPF_DSWAP_P_WDS, | ||
56 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | ||
57 | { V4L2_PIX_FMT_RGB555, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
58 | VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
59 | VI6_RPF_DSWAP_P_WDS, | ||
60 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | ||
61 | { V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
62 | VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
63 | VI6_RPF_DSWAP_P_WDS, | ||
64 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | ||
65 | { V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
66 | VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
67 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
68 | 1, { 24, 0, 0 }, false, false, 1, 1 }, | ||
69 | { V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
70 | VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
71 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
72 | 1, { 24, 0, 0 }, false, false, 1, 1 }, | ||
73 | { V4L2_PIX_FMT_BGR32, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
74 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, | ||
75 | 1, { 32, 0, 0 }, false, false, 1, 1 }, | ||
76 | { V4L2_PIX_FMT_RGB32, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
77 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
78 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
79 | 1, { 32, 0, 0 }, false, false, 1, 1 }, | ||
80 | { V4L2_PIX_FMT_UYVY, V4L2_MBUS_FMT_AYUV8_1X32, | ||
81 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
82 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
83 | 1, { 16, 0, 0 }, false, false, 2, 1 }, | ||
84 | { V4L2_PIX_FMT_VYUY, V4L2_MBUS_FMT_AYUV8_1X32, | ||
85 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
86 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
87 | 1, { 16, 0, 0 }, false, true, 2, 1 }, | ||
88 | { V4L2_PIX_FMT_YUYV, V4L2_MBUS_FMT_AYUV8_1X32, | ||
89 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
90 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
91 | 1, { 16, 0, 0 }, true, false, 2, 1 }, | ||
92 | { V4L2_PIX_FMT_YVYU, V4L2_MBUS_FMT_AYUV8_1X32, | ||
93 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
94 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
95 | 1, { 16, 0, 0 }, true, true, 2, 1 }, | ||
96 | { V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
97 | VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
98 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
99 | 2, { 8, 16, 0 }, false, false, 2, 2 }, | ||
100 | { V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
101 | VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
102 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
103 | 2, { 8, 16, 0 }, false, true, 2, 2 }, | ||
104 | { V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
105 | VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
106 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
107 | 2, { 8, 16, 0 }, false, false, 2, 1 }, | ||
108 | { V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
109 | VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
110 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
111 | 2, { 8, 16, 0 }, false, true, 2, 1 }, | ||
112 | { V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
113 | VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
114 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
115 | 3, { 8, 8, 8 }, false, false, 2, 2 }, | ||
116 | }; | ||
117 | |||
118 | /* | ||
119 | * vsp1_get_format_info - Retrieve format information for a 4CC | ||
120 | * @fourcc: the format 4CC | ||
121 | * | ||
122 | * Return a pointer to the format information structure corresponding to the | ||
123 | * given V4L2 format 4CC, or NULL if no corresponding format can be found. | ||
124 | */ | ||
125 | static const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc) | ||
126 | { | ||
127 | unsigned int i; | ||
128 | |||
129 | for (i = 0; i < ARRAY_SIZE(vsp1_video_formats); ++i) { | ||
130 | const struct vsp1_format_info *info = &vsp1_video_formats[i]; | ||
131 | |||
132 | if (info->fourcc == fourcc) | ||
133 | return info; | ||
134 | } | ||
135 | |||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | |||
140 | static struct v4l2_subdev * | ||
141 | vsp1_video_remote_subdev(struct media_pad *local, u32 *pad) | ||
142 | { | ||
143 | struct media_pad *remote; | ||
144 | |||
145 | remote = media_entity_remote_pad(local); | ||
146 | if (remote == NULL || | ||
147 | media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
148 | return NULL; | ||
149 | |||
150 | if (pad) | ||
151 | *pad = remote->index; | ||
152 | |||
153 | return media_entity_to_v4l2_subdev(remote->entity); | ||
154 | } | ||
155 | |||
156 | static int vsp1_video_verify_format(struct vsp1_video *video) | ||
157 | { | ||
158 | struct v4l2_subdev_format fmt; | ||
159 | struct v4l2_subdev *subdev; | ||
160 | int ret; | ||
161 | |||
162 | subdev = vsp1_video_remote_subdev(&video->pad, &fmt.pad); | ||
163 | if (subdev == NULL) | ||
164 | return -EINVAL; | ||
165 | |||
166 | fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; | ||
167 | ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); | ||
168 | if (ret < 0) | ||
169 | return ret == -ENOIOCTLCMD ? -EINVAL : ret; | ||
170 | |||
171 | if (video->fmtinfo->mbus != fmt.format.code || | ||
172 | video->format.height != fmt.format.height || | ||
173 | video->format.width != fmt.format.width) | ||
174 | return -EINVAL; | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int __vsp1_video_try_format(struct vsp1_video *video, | ||
180 | struct v4l2_pix_format_mplane *pix, | ||
181 | const struct vsp1_format_info **fmtinfo) | ||
182 | { | ||
183 | const struct vsp1_format_info *info; | ||
184 | unsigned int width = pix->width; | ||
185 | unsigned int height = pix->height; | ||
186 | unsigned int i; | ||
187 | |||
188 | /* Retrieve format information and select the default format if the | ||
189 | * requested format isn't supported. | ||
190 | */ | ||
191 | info = vsp1_get_format_info(pix->pixelformat); | ||
192 | if (info == NULL) | ||
193 | info = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); | ||
194 | |||
195 | pix->pixelformat = info->fourcc; | ||
196 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
197 | pix->field = V4L2_FIELD_NONE; | ||
198 | memset(pix->reserved, 0, sizeof(pix->reserved)); | ||
199 | |||
200 | /* Align the width and height for YUV 4:2:2 and 4:2:0 formats. */ | ||
201 | width = round_down(width, info->hsub); | ||
202 | height = round_down(height, info->vsub); | ||
203 | |||
204 | /* Clamp the width and height. */ | ||
205 | pix->width = clamp(width, VSP1_VIDEO_MIN_WIDTH, VSP1_VIDEO_MAX_WIDTH); | ||
206 | pix->height = clamp(height, VSP1_VIDEO_MIN_HEIGHT, | ||
207 | VSP1_VIDEO_MAX_HEIGHT); | ||
208 | |||
209 | /* Compute and clamp the stride and image size. While not documented in | ||
210 | * the datasheet, strides not aligned to a multiple of 128 bytes result | ||
211 | * in image corruption. | ||
212 | */ | ||
213 | for (i = 0; i < max(info->planes, 2U); ++i) { | ||
214 | unsigned int hsub = i > 0 ? info->hsub : 1; | ||
215 | unsigned int vsub = i > 0 ? info->vsub : 1; | ||
216 | unsigned int align = 128; | ||
217 | unsigned int bpl; | ||
218 | |||
219 | bpl = clamp_t(unsigned int, pix->plane_fmt[i].bytesperline, | ||
220 | pix->width / hsub * info->bpp[i] / 8, | ||
221 | round_down(65535U, align)); | ||
222 | |||
223 | pix->plane_fmt[i].bytesperline = round_up(bpl, align); | ||
224 | pix->plane_fmt[i].sizeimage = pix->plane_fmt[i].bytesperline | ||
225 | * pix->height / vsub; | ||
226 | } | ||
227 | |||
228 | if (info->planes == 3) { | ||
229 | /* The second and third planes must have the same stride. */ | ||
230 | pix->plane_fmt[2].bytesperline = pix->plane_fmt[1].bytesperline; | ||
231 | pix->plane_fmt[2].sizeimage = pix->plane_fmt[1].sizeimage; | ||
232 | } | ||
233 | |||
234 | pix->num_planes = info->planes; | ||
235 | |||
236 | if (fmtinfo) | ||
237 | *fmtinfo = info; | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static bool | ||
243 | vsp1_video_format_adjust(struct vsp1_video *video, | ||
244 | const struct v4l2_pix_format_mplane *format, | ||
245 | struct v4l2_pix_format_mplane *adjust) | ||
246 | { | ||
247 | unsigned int i; | ||
248 | |||
249 | *adjust = *format; | ||
250 | __vsp1_video_try_format(video, adjust, NULL); | ||
251 | |||
252 | if (format->width != adjust->width || | ||
253 | format->height != adjust->height || | ||
254 | format->pixelformat != adjust->pixelformat || | ||
255 | format->num_planes != adjust->num_planes) | ||
256 | return false; | ||
257 | |||
258 | for (i = 0; i < format->num_planes; ++i) { | ||
259 | if (format->plane_fmt[i].bytesperline != | ||
260 | adjust->plane_fmt[i].bytesperline) | ||
261 | return false; | ||
262 | |||
263 | adjust->plane_fmt[i].sizeimage = | ||
264 | max(adjust->plane_fmt[i].sizeimage, | ||
265 | format->plane_fmt[i].sizeimage); | ||
266 | } | ||
267 | |||
268 | return true; | ||
269 | } | ||
270 | |||
271 | /* ----------------------------------------------------------------------------- | ||
272 | * Pipeline Management | ||
273 | */ | ||
274 | |||
275 | static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, | ||
276 | struct vsp1_rwpf *output) | ||
277 | { | ||
278 | struct vsp1_entity *entity; | ||
279 | unsigned int entities = 0; | ||
280 | struct media_pad *pad; | ||
281 | bool uds_found = false; | ||
282 | |||
283 | pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); | ||
284 | |||
285 | while (1) { | ||
286 | if (pad == NULL) | ||
287 | return -EPIPE; | ||
288 | |||
289 | /* We've reached a video node, that shouldn't have happened. */ | ||
290 | if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
291 | return -EPIPE; | ||
292 | |||
293 | entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); | ||
294 | |||
295 | /* We've reached the WPF, we're done. */ | ||
296 | if (entity->type == VSP1_ENTITY_WPF) | ||
297 | break; | ||
298 | |||
299 | /* Ensure the branch has no loop. */ | ||
300 | if (entities & (1 << entity->subdev.entity.id)) | ||
301 | return -EPIPE; | ||
302 | |||
303 | entities |= 1 << entity->subdev.entity.id; | ||
304 | |||
305 | /* UDS can't be chained. */ | ||
306 | if (entity->type == VSP1_ENTITY_UDS) { | ||
307 | if (uds_found) | ||
308 | return -EPIPE; | ||
309 | uds_found = true; | ||
310 | } | ||
311 | |||
312 | /* Follow the source link. The link setup operations ensure | ||
313 | * that the output fan-out can't be more than one, there is thus | ||
314 | * no need to verify here that only a single source link is | ||
315 | * activated. | ||
316 | */ | ||
317 | pad = &entity->pads[entity->source_pad]; | ||
318 | pad = media_entity_remote_pad(pad); | ||
319 | } | ||
320 | |||
321 | /* The last entity must be the output WPF. */ | ||
322 | if (entity != &output->entity) | ||
323 | return -EPIPE; | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | ||
329 | struct vsp1_video *video) | ||
330 | { | ||
331 | struct media_entity_graph graph; | ||
332 | struct media_entity *entity = &video->video.entity; | ||
333 | struct media_device *mdev = entity->parent; | ||
334 | unsigned int i; | ||
335 | int ret; | ||
336 | |||
337 | mutex_lock(&mdev->graph_mutex); | ||
338 | |||
339 | /* Walk the graph to locate the entities and video nodes. */ | ||
340 | media_entity_graph_walk_start(&graph, entity); | ||
341 | |||
342 | while ((entity = media_entity_graph_walk_next(&graph))) { | ||
343 | struct v4l2_subdev *subdev; | ||
344 | struct vsp1_rwpf *rwpf; | ||
345 | struct vsp1_entity *e; | ||
346 | |||
347 | if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) { | ||
348 | pipe->num_video++; | ||
349 | continue; | ||
350 | } | ||
351 | |||
352 | subdev = media_entity_to_v4l2_subdev(entity); | ||
353 | e = to_vsp1_entity(subdev); | ||
354 | list_add_tail(&e->list_pipe, &pipe->entities); | ||
355 | |||
356 | if (e->type == VSP1_ENTITY_RPF) { | ||
357 | rwpf = to_rwpf(subdev); | ||
358 | pipe->inputs[pipe->num_inputs++] = rwpf; | ||
359 | rwpf->video.pipe_index = pipe->num_inputs; | ||
360 | } else if (e->type == VSP1_ENTITY_WPF) { | ||
361 | rwpf = to_rwpf(subdev); | ||
362 | pipe->output = to_rwpf(subdev); | ||
363 | rwpf->video.pipe_index = 0; | ||
364 | } else if (e->type == VSP1_ENTITY_LIF) { | ||
365 | pipe->lif = e; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | mutex_unlock(&mdev->graph_mutex); | ||
370 | |||
371 | /* We need one output and at least one input. */ | ||
372 | if (pipe->num_inputs == 0 || !pipe->output) { | ||
373 | ret = -EPIPE; | ||
374 | goto error; | ||
375 | } | ||
376 | |||
377 | /* Follow links downstream for each input and make sure the graph | ||
378 | * contains no loop and that all branches end at the output WPF. | ||
379 | */ | ||
380 | for (i = 0; i < pipe->num_inputs; ++i) { | ||
381 | ret = vsp1_pipeline_validate_branch(pipe->inputs[i], | ||
382 | pipe->output); | ||
383 | if (ret < 0) | ||
384 | goto error; | ||
385 | } | ||
386 | |||
387 | return 0; | ||
388 | |||
389 | error: | ||
390 | INIT_LIST_HEAD(&pipe->entities); | ||
391 | pipe->buffers_ready = 0; | ||
392 | pipe->num_video = 0; | ||
393 | pipe->num_inputs = 0; | ||
394 | pipe->output = NULL; | ||
395 | pipe->lif = NULL; | ||
396 | return ret; | ||
397 | } | ||
398 | |||
399 | static int vsp1_pipeline_init(struct vsp1_pipeline *pipe, | ||
400 | struct vsp1_video *video) | ||
401 | { | ||
402 | int ret; | ||
403 | |||
404 | mutex_lock(&pipe->lock); | ||
405 | |||
406 | /* If we're the first user validate and initialize the pipeline. */ | ||
407 | if (pipe->use_count == 0) { | ||
408 | ret = vsp1_pipeline_validate(pipe, video); | ||
409 | if (ret < 0) | ||
410 | goto done; | ||
411 | } | ||
412 | |||
413 | pipe->use_count++; | ||
414 | ret = 0; | ||
415 | |||
416 | done: | ||
417 | mutex_unlock(&pipe->lock); | ||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) | ||
422 | { | ||
423 | mutex_lock(&pipe->lock); | ||
424 | |||
425 | /* If we're the last user clean up the pipeline. */ | ||
426 | if (--pipe->use_count == 0) { | ||
427 | INIT_LIST_HEAD(&pipe->entities); | ||
428 | pipe->state = VSP1_PIPELINE_STOPPED; | ||
429 | pipe->buffers_ready = 0; | ||
430 | pipe->num_video = 0; | ||
431 | pipe->num_inputs = 0; | ||
432 | pipe->output = NULL; | ||
433 | pipe->lif = NULL; | ||
434 | } | ||
435 | |||
436 | mutex_unlock(&pipe->lock); | ||
437 | } | ||
438 | |||
439 | static void vsp1_pipeline_run(struct vsp1_pipeline *pipe) | ||
440 | { | ||
441 | struct vsp1_device *vsp1 = pipe->output->entity.vsp1; | ||
442 | |||
443 | vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD); | ||
444 | pipe->state = VSP1_PIPELINE_RUNNING; | ||
445 | pipe->buffers_ready = 0; | ||
446 | } | ||
447 | |||
448 | static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) | ||
449 | { | ||
450 | struct vsp1_entity *entity; | ||
451 | unsigned long flags; | ||
452 | int ret; | ||
453 | |||
454 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
455 | pipe->state = VSP1_PIPELINE_STOPPING; | ||
456 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
457 | |||
458 | ret = wait_event_timeout(pipe->wq, pipe->state == VSP1_PIPELINE_STOPPED, | ||
459 | msecs_to_jiffies(500)); | ||
460 | ret = ret == 0 ? -ETIMEDOUT : 0; | ||
461 | |||
462 | list_for_each_entry(entity, &pipe->entities, list_pipe) { | ||
463 | if (entity->route) | ||
464 | vsp1_write(entity->vsp1, entity->route, | ||
465 | VI6_DPR_NODE_UNUSED); | ||
466 | |||
467 | v4l2_subdev_call(&entity->subdev, video, s_stream, 0); | ||
468 | } | ||
469 | |||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | static bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) | ||
474 | { | ||
475 | unsigned int mask; | ||
476 | |||
477 | mask = ((1 << pipe->num_inputs) - 1) << 1; | ||
478 | if (!pipe->lif) | ||
479 | mask |= 1 << 0; | ||
480 | |||
481 | return pipe->buffers_ready == mask; | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * vsp1_video_complete_buffer - Complete the current buffer | ||
486 | * @video: the video node | ||
487 | * | ||
488 | * This function completes the current buffer by filling its sequence number, | ||
489 | * time stamp and payload size, and hands it back to the videobuf core. | ||
490 | * | ||
491 | * Return the next queued buffer or NULL if the queue is empty. | ||
492 | */ | ||
493 | static struct vsp1_video_buffer * | ||
494 | vsp1_video_complete_buffer(struct vsp1_video *video) | ||
495 | { | ||
496 | struct vsp1_video_buffer *next = NULL; | ||
497 | struct vsp1_video_buffer *done; | ||
498 | unsigned long flags; | ||
499 | unsigned int i; | ||
500 | |||
501 | spin_lock_irqsave(&video->irqlock, flags); | ||
502 | |||
503 | if (list_empty(&video->irqqueue)) { | ||
504 | spin_unlock_irqrestore(&video->irqlock, flags); | ||
505 | return NULL; | ||
506 | } | ||
507 | |||
508 | done = list_first_entry(&video->irqqueue, | ||
509 | struct vsp1_video_buffer, queue); | ||
510 | list_del(&done->queue); | ||
511 | |||
512 | if (!list_empty(&video->irqqueue)) | ||
513 | next = list_first_entry(&video->irqqueue, | ||
514 | struct vsp1_video_buffer, queue); | ||
515 | |||
516 | spin_unlock_irqrestore(&video->irqlock, flags); | ||
517 | |||
518 | done->buf.v4l2_buf.sequence = video->sequence++; | ||
519 | v4l2_get_timestamp(&done->buf.v4l2_buf.timestamp); | ||
520 | for (i = 0; i < done->buf.num_planes; ++i) | ||
521 | vb2_set_plane_payload(&done->buf, i, done->length[i]); | ||
522 | vb2_buffer_done(&done->buf, VB2_BUF_STATE_DONE); | ||
523 | |||
524 | return next; | ||
525 | } | ||
526 | |||
527 | static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, | ||
528 | struct vsp1_video *video) | ||
529 | { | ||
530 | struct vsp1_video_buffer *buf; | ||
531 | unsigned long flags; | ||
532 | |||
533 | buf = vsp1_video_complete_buffer(video); | ||
534 | if (buf == NULL) | ||
535 | return; | ||
536 | |||
537 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
538 | |||
539 | video->ops->queue(video, buf); | ||
540 | pipe->buffers_ready |= 1 << video->pipe_index; | ||
541 | |||
542 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
543 | } | ||
544 | |||
545 | void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) | ||
546 | { | ||
547 | unsigned long flags; | ||
548 | unsigned int i; | ||
549 | |||
550 | if (pipe == NULL) | ||
551 | return; | ||
552 | |||
553 | /* Complete buffers on all video nodes. */ | ||
554 | for (i = 0; i < pipe->num_inputs; ++i) | ||
555 | vsp1_video_frame_end(pipe, &pipe->inputs[i]->video); | ||
556 | |||
557 | if (!pipe->lif) | ||
558 | vsp1_video_frame_end(pipe, &pipe->output->video); | ||
559 | |||
560 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
561 | |||
562 | /* If a stop has been requested, mark the pipeline as stopped and | ||
563 | * return. | ||
564 | */ | ||
565 | if (pipe->state == VSP1_PIPELINE_STOPPING) { | ||
566 | pipe->state = VSP1_PIPELINE_STOPPED; | ||
567 | wake_up(&pipe->wq); | ||
568 | goto done; | ||
569 | } | ||
570 | |||
571 | /* Restart the pipeline if ready. */ | ||
572 | if (vsp1_pipeline_ready(pipe)) | ||
573 | vsp1_pipeline_run(pipe); | ||
574 | |||
575 | done: | ||
576 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
577 | } | ||
578 | |||
579 | /* ----------------------------------------------------------------------------- | ||
580 | * videobuf2 Queue Operations | ||
581 | */ | ||
582 | |||
583 | static int | ||
584 | vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | ||
585 | unsigned int *nbuffers, unsigned int *nplanes, | ||
586 | unsigned int sizes[], void *alloc_ctxs[]) | ||
587 | { | ||
588 | struct vsp1_video *video = vb2_get_drv_priv(vq); | ||
589 | const struct v4l2_pix_format_mplane *format; | ||
590 | struct v4l2_pix_format_mplane pix_mp; | ||
591 | unsigned int i; | ||
592 | |||
593 | if (fmt) { | ||
594 | /* Make sure the format is valid and adjust the sizeimage field | ||
595 | * if needed. | ||
596 | */ | ||
597 | if (!vsp1_video_format_adjust(video, &fmt->fmt.pix_mp, &pix_mp)) | ||
598 | return -EINVAL; | ||
599 | |||
600 | format = &pix_mp; | ||
601 | } else { | ||
602 | format = &video->format; | ||
603 | } | ||
604 | |||
605 | *nplanes = format->num_planes; | ||
606 | |||
607 | for (i = 0; i < format->num_planes; ++i) { | ||
608 | sizes[i] = format->plane_fmt[i].sizeimage; | ||
609 | alloc_ctxs[i] = video->alloc_ctx; | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) | ||
616 | { | ||
617 | struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); | ||
618 | struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb); | ||
619 | const struct v4l2_pix_format_mplane *format = &video->format; | ||
620 | unsigned int i; | ||
621 | |||
622 | if (vb->num_planes < format->num_planes) | ||
623 | return -EINVAL; | ||
624 | |||
625 | buf->video = video; | ||
626 | |||
627 | for (i = 0; i < vb->num_planes; ++i) { | ||
628 | buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); | ||
629 | buf->length[i] = vb2_plane_size(vb, i); | ||
630 | |||
631 | if (buf->length[i] < format->plane_fmt[i].sizeimage) | ||
632 | return -EINVAL; | ||
633 | } | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static void vsp1_video_buffer_queue(struct vb2_buffer *vb) | ||
639 | { | ||
640 | struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); | ||
641 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); | ||
642 | struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb); | ||
643 | unsigned long flags; | ||
644 | bool empty; | ||
645 | |||
646 | spin_lock_irqsave(&video->irqlock, flags); | ||
647 | empty = list_empty(&video->irqqueue); | ||
648 | list_add_tail(&buf->queue, &video->irqqueue); | ||
649 | spin_unlock_irqrestore(&video->irqlock, flags); | ||
650 | |||
651 | if (!empty) | ||
652 | return; | ||
653 | |||
654 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
655 | |||
656 | video->ops->queue(video, buf); | ||
657 | pipe->buffers_ready |= 1 << video->pipe_index; | ||
658 | |||
659 | if (vb2_is_streaming(&video->queue) && | ||
660 | vsp1_pipeline_ready(pipe)) | ||
661 | vsp1_pipeline_run(pipe); | ||
662 | |||
663 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
664 | } | ||
665 | |||
666 | static void vsp1_entity_route_setup(struct vsp1_entity *source) | ||
667 | { | ||
668 | struct vsp1_entity *sink; | ||
669 | |||
670 | if (source->route == 0) | ||
671 | return; | ||
672 | |||
673 | sink = container_of(source->sink, struct vsp1_entity, subdev.entity); | ||
674 | vsp1_write(source->vsp1, source->route, sink->id); | ||
675 | } | ||
676 | |||
677 | static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) | ||
678 | { | ||
679 | struct vsp1_video *video = vb2_get_drv_priv(vq); | ||
680 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); | ||
681 | struct vsp1_entity *entity; | ||
682 | unsigned long flags; | ||
683 | int ret; | ||
684 | |||
685 | mutex_lock(&pipe->lock); | ||
686 | if (pipe->stream_count == pipe->num_video - 1) { | ||
687 | list_for_each_entry(entity, &pipe->entities, list_pipe) { | ||
688 | vsp1_entity_route_setup(entity); | ||
689 | |||
690 | ret = v4l2_subdev_call(&entity->subdev, video, | ||
691 | s_stream, 1); | ||
692 | if (ret < 0) { | ||
693 | mutex_unlock(&pipe->lock); | ||
694 | return ret; | ||
695 | } | ||
696 | } | ||
697 | } | ||
698 | |||
699 | pipe->stream_count++; | ||
700 | mutex_unlock(&pipe->lock); | ||
701 | |||
702 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
703 | if (vsp1_pipeline_ready(pipe)) | ||
704 | vsp1_pipeline_run(pipe); | ||
705 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
706 | |||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | static int vsp1_video_stop_streaming(struct vb2_queue *vq) | ||
711 | { | ||
712 | struct vsp1_video *video = vb2_get_drv_priv(vq); | ||
713 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); | ||
714 | unsigned long flags; | ||
715 | int ret; | ||
716 | |||
717 | mutex_lock(&pipe->lock); | ||
718 | if (--pipe->stream_count == 0) { | ||
719 | /* Stop the pipeline. */ | ||
720 | ret = vsp1_pipeline_stop(pipe); | ||
721 | if (ret == -ETIMEDOUT) | ||
722 | dev_err(video->vsp1->dev, "pipeline stop timeout\n"); | ||
723 | } | ||
724 | mutex_unlock(&pipe->lock); | ||
725 | |||
726 | vsp1_pipeline_cleanup(pipe); | ||
727 | media_entity_pipeline_stop(&video->video.entity); | ||
728 | |||
729 | /* Remove all buffers from the IRQ queue. */ | ||
730 | spin_lock_irqsave(&video->irqlock, flags); | ||
731 | INIT_LIST_HEAD(&video->irqqueue); | ||
732 | spin_unlock_irqrestore(&video->irqlock, flags); | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | static struct vb2_ops vsp1_video_queue_qops = { | ||
738 | .queue_setup = vsp1_video_queue_setup, | ||
739 | .buf_prepare = vsp1_video_buffer_prepare, | ||
740 | .buf_queue = vsp1_video_buffer_queue, | ||
741 | .wait_prepare = vb2_ops_wait_prepare, | ||
742 | .wait_finish = vb2_ops_wait_finish, | ||
743 | .start_streaming = vsp1_video_start_streaming, | ||
744 | .stop_streaming = vsp1_video_stop_streaming, | ||
745 | }; | ||
746 | |||
747 | /* ----------------------------------------------------------------------------- | ||
748 | * V4L2 ioctls | ||
749 | */ | ||
750 | |||
751 | static int | ||
752 | vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) | ||
753 | { | ||
754 | struct v4l2_fh *vfh = file->private_data; | ||
755 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
756 | |||
757 | cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING | ||
758 | | V4L2_CAP_VIDEO_CAPTURE_MPLANE | ||
759 | | V4L2_CAP_VIDEO_OUTPUT_MPLANE; | ||
760 | |||
761 | if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | ||
762 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | ||
763 | | V4L2_CAP_STREAMING; | ||
764 | else | ||
765 | cap->device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE | ||
766 | | V4L2_CAP_STREAMING; | ||
767 | |||
768 | strlcpy(cap->driver, "vsp1", sizeof(cap->driver)); | ||
769 | strlcpy(cap->card, video->video.name, sizeof(cap->card)); | ||
770 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", | ||
771 | dev_name(video->vsp1->dev)); | ||
772 | |||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | static int | ||
777 | vsp1_video_get_format(struct file *file, void *fh, struct v4l2_format *format) | ||
778 | { | ||
779 | struct v4l2_fh *vfh = file->private_data; | ||
780 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
781 | |||
782 | if (format->type != video->queue.type) | ||
783 | return -EINVAL; | ||
784 | |||
785 | mutex_lock(&video->lock); | ||
786 | format->fmt.pix_mp = video->format; | ||
787 | mutex_unlock(&video->lock); | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static int | ||
793 | vsp1_video_try_format(struct file *file, void *fh, struct v4l2_format *format) | ||
794 | { | ||
795 | struct v4l2_fh *vfh = file->private_data; | ||
796 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
797 | |||
798 | if (format->type != video->queue.type) | ||
799 | return -EINVAL; | ||
800 | |||
801 | return __vsp1_video_try_format(video, &format->fmt.pix_mp, NULL); | ||
802 | } | ||
803 | |||
804 | static int | ||
805 | vsp1_video_set_format(struct file *file, void *fh, struct v4l2_format *format) | ||
806 | { | ||
807 | struct v4l2_fh *vfh = file->private_data; | ||
808 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
809 | const struct vsp1_format_info *info; | ||
810 | int ret; | ||
811 | |||
812 | if (format->type != video->queue.type) | ||
813 | return -EINVAL; | ||
814 | |||
815 | ret = __vsp1_video_try_format(video, &format->fmt.pix_mp, &info); | ||
816 | if (ret < 0) | ||
817 | return ret; | ||
818 | |||
819 | mutex_lock(&video->lock); | ||
820 | |||
821 | if (vb2_is_busy(&video->queue)) { | ||
822 | ret = -EBUSY; | ||
823 | goto done; | ||
824 | } | ||
825 | |||
826 | video->format = format->fmt.pix_mp; | ||
827 | video->fmtinfo = info; | ||
828 | |||
829 | done: | ||
830 | mutex_unlock(&video->lock); | ||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | static int | ||
835 | vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) | ||
836 | { | ||
837 | struct v4l2_fh *vfh = file->private_data; | ||
838 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
839 | struct vsp1_pipeline *pipe; | ||
840 | int ret; | ||
841 | |||
842 | if (video->queue.owner && video->queue.owner != file->private_data) | ||
843 | return -EBUSY; | ||
844 | |||
845 | video->sequence = 0; | ||
846 | |||
847 | /* Start streaming on the pipeline. No link touching an entity in the | ||
848 | * pipeline can be activated or deactivated once streaming is started. | ||
849 | * | ||
850 | * Use the VSP1 pipeline object embedded in the first video object that | ||
851 | * starts streaming. | ||
852 | */ | ||
853 | pipe = video->video.entity.pipe | ||
854 | ? to_vsp1_pipeline(&video->video.entity) : &video->pipe; | ||
855 | |||
856 | ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe); | ||
857 | if (ret < 0) | ||
858 | return ret; | ||
859 | |||
860 | /* Verify that the configured format matches the output of the connected | ||
861 | * subdev. | ||
862 | */ | ||
863 | ret = vsp1_video_verify_format(video); | ||
864 | if (ret < 0) | ||
865 | goto err_stop; | ||
866 | |||
867 | ret = vsp1_pipeline_init(pipe, video); | ||
868 | if (ret < 0) | ||
869 | goto err_stop; | ||
870 | |||
871 | /* Start the queue. */ | ||
872 | ret = vb2_streamon(&video->queue, type); | ||
873 | if (ret < 0) | ||
874 | goto err_cleanup; | ||
875 | |||
876 | return 0; | ||
877 | |||
878 | err_cleanup: | ||
879 | vsp1_pipeline_cleanup(pipe); | ||
880 | err_stop: | ||
881 | media_entity_pipeline_stop(&video->video.entity); | ||
882 | return ret; | ||
883 | } | ||
884 | |||
885 | static const struct v4l2_ioctl_ops vsp1_video_ioctl_ops = { | ||
886 | .vidioc_querycap = vsp1_video_querycap, | ||
887 | .vidioc_g_fmt_vid_cap_mplane = vsp1_video_get_format, | ||
888 | .vidioc_s_fmt_vid_cap_mplane = vsp1_video_set_format, | ||
889 | .vidioc_try_fmt_vid_cap_mplane = vsp1_video_try_format, | ||
890 | .vidioc_g_fmt_vid_out_mplane = vsp1_video_get_format, | ||
891 | .vidioc_s_fmt_vid_out_mplane = vsp1_video_set_format, | ||
892 | .vidioc_try_fmt_vid_out_mplane = vsp1_video_try_format, | ||
893 | .vidioc_reqbufs = vb2_ioctl_reqbufs, | ||
894 | .vidioc_querybuf = vb2_ioctl_querybuf, | ||
895 | .vidioc_qbuf = vb2_ioctl_qbuf, | ||
896 | .vidioc_dqbuf = vb2_ioctl_dqbuf, | ||
897 | .vidioc_create_bufs = vb2_ioctl_create_bufs, | ||
898 | .vidioc_prepare_buf = vb2_ioctl_prepare_buf, | ||
899 | .vidioc_streamon = vsp1_video_streamon, | ||
900 | .vidioc_streamoff = vb2_ioctl_streamoff, | ||
901 | }; | ||
902 | |||
903 | /* ----------------------------------------------------------------------------- | ||
904 | * V4L2 File Operations | ||
905 | */ | ||
906 | |||
907 | static int vsp1_video_open(struct file *file) | ||
908 | { | ||
909 | struct vsp1_video *video = video_drvdata(file); | ||
910 | struct v4l2_fh *vfh; | ||
911 | int ret = 0; | ||
912 | |||
913 | vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); | ||
914 | if (vfh == NULL) | ||
915 | return -ENOMEM; | ||
916 | |||
917 | v4l2_fh_init(vfh, &video->video); | ||
918 | v4l2_fh_add(vfh); | ||
919 | |||
920 | file->private_data = vfh; | ||
921 | |||
922 | if (!vsp1_device_get(video->vsp1)) { | ||
923 | ret = -EBUSY; | ||
924 | v4l2_fh_del(vfh); | ||
925 | kfree(vfh); | ||
926 | } | ||
927 | |||
928 | return ret; | ||
929 | } | ||
930 | |||
931 | static int vsp1_video_release(struct file *file) | ||
932 | { | ||
933 | struct vsp1_video *video = video_drvdata(file); | ||
934 | struct v4l2_fh *vfh = file->private_data; | ||
935 | |||
936 | mutex_lock(&video->lock); | ||
937 | if (video->queue.owner == vfh) { | ||
938 | vb2_queue_release(&video->queue); | ||
939 | video->queue.owner = NULL; | ||
940 | } | ||
941 | mutex_unlock(&video->lock); | ||
942 | |||
943 | vsp1_device_put(video->vsp1); | ||
944 | |||
945 | v4l2_fh_release(file); | ||
946 | |||
947 | file->private_data = NULL; | ||
948 | |||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | static struct v4l2_file_operations vsp1_video_fops = { | ||
953 | .owner = THIS_MODULE, | ||
954 | .unlocked_ioctl = video_ioctl2, | ||
955 | .open = vsp1_video_open, | ||
956 | .release = vsp1_video_release, | ||
957 | .poll = vb2_fop_poll, | ||
958 | .mmap = vb2_fop_mmap, | ||
959 | }; | ||
960 | |||
961 | /* ----------------------------------------------------------------------------- | ||
962 | * Initialization and Cleanup | ||
963 | */ | ||
964 | |||
965 | int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf) | ||
966 | { | ||
967 | const char *direction; | ||
968 | int ret; | ||
969 | |||
970 | switch (video->type) { | ||
971 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: | ||
972 | direction = "output"; | ||
973 | video->pad.flags = MEDIA_PAD_FL_SINK; | ||
974 | break; | ||
975 | |||
976 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: | ||
977 | direction = "input"; | ||
978 | video->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
979 | video->video.vfl_dir = VFL_DIR_TX; | ||
980 | break; | ||
981 | |||
982 | default: | ||
983 | return -EINVAL; | ||
984 | } | ||
985 | |||
986 | video->rwpf = rwpf; | ||
987 | |||
988 | mutex_init(&video->lock); | ||
989 | spin_lock_init(&video->irqlock); | ||
990 | INIT_LIST_HEAD(&video->irqqueue); | ||
991 | |||
992 | mutex_init(&video->pipe.lock); | ||
993 | spin_lock_init(&video->pipe.irqlock); | ||
994 | INIT_LIST_HEAD(&video->pipe.entities); | ||
995 | init_waitqueue_head(&video->pipe.wq); | ||
996 | video->pipe.state = VSP1_PIPELINE_STOPPED; | ||
997 | |||
998 | /* Initialize the media entity... */ | ||
999 | ret = media_entity_init(&video->video.entity, 1, &video->pad, 0); | ||
1000 | if (ret < 0) | ||
1001 | return ret; | ||
1002 | |||
1003 | /* ... and the format ... */ | ||
1004 | video->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); | ||
1005 | video->format.pixelformat = video->fmtinfo->fourcc; | ||
1006 | video->format.colorspace = V4L2_COLORSPACE_SRGB; | ||
1007 | video->format.field = V4L2_FIELD_NONE; | ||
1008 | video->format.width = VSP1_VIDEO_DEF_WIDTH; | ||
1009 | video->format.height = VSP1_VIDEO_DEF_HEIGHT; | ||
1010 | video->format.num_planes = 1; | ||
1011 | video->format.plane_fmt[0].bytesperline = | ||
1012 | video->format.width * video->fmtinfo->bpp[0] / 8; | ||
1013 | video->format.plane_fmt[0].sizeimage = | ||
1014 | video->format.plane_fmt[0].bytesperline * video->format.height; | ||
1015 | |||
1016 | /* ... and the video node... */ | ||
1017 | video->video.v4l2_dev = &video->vsp1->v4l2_dev; | ||
1018 | video->video.fops = &vsp1_video_fops; | ||
1019 | snprintf(video->video.name, sizeof(video->video.name), "%s %s", | ||
1020 | rwpf->subdev.name, direction); | ||
1021 | video->video.vfl_type = VFL_TYPE_GRABBER; | ||
1022 | video->video.release = video_device_release_empty; | ||
1023 | video->video.ioctl_ops = &vsp1_video_ioctl_ops; | ||
1024 | |||
1025 | video_set_drvdata(&video->video, video); | ||
1026 | |||
1027 | /* ... and the buffers queue... */ | ||
1028 | video->alloc_ctx = vb2_dma_contig_init_ctx(video->vsp1->dev); | ||
1029 | if (IS_ERR(video->alloc_ctx)) | ||
1030 | goto error; | ||
1031 | |||
1032 | video->queue.type = video->type; | ||
1033 | video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; | ||
1034 | video->queue.lock = &video->lock; | ||
1035 | video->queue.drv_priv = video; | ||
1036 | video->queue.buf_struct_size = sizeof(struct vsp1_video_buffer); | ||
1037 | video->queue.ops = &vsp1_video_queue_qops; | ||
1038 | video->queue.mem_ops = &vb2_dma_contig_memops; | ||
1039 | video->queue.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; | ||
1040 | ret = vb2_queue_init(&video->queue); | ||
1041 | if (ret < 0) { | ||
1042 | dev_err(video->vsp1->dev, "failed to initialize vb2 queue\n"); | ||
1043 | goto error; | ||
1044 | } | ||
1045 | |||
1046 | /* ... and register the video device. */ | ||
1047 | video->video.queue = &video->queue; | ||
1048 | ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1); | ||
1049 | if (ret < 0) { | ||
1050 | dev_err(video->vsp1->dev, "failed to register video device\n"); | ||
1051 | goto error; | ||
1052 | } | ||
1053 | |||
1054 | return 0; | ||
1055 | |||
1056 | error: | ||
1057 | vb2_dma_contig_cleanup_ctx(video->alloc_ctx); | ||
1058 | vsp1_video_cleanup(video); | ||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | void vsp1_video_cleanup(struct vsp1_video *video) | ||
1063 | { | ||
1064 | if (video_is_registered(&video->video)) | ||
1065 | video_unregister_device(&video->video); | ||
1066 | |||
1067 | vb2_dma_contig_cleanup_ctx(video->alloc_ctx); | ||
1068 | media_entity_cleanup(&video->video.entity); | ||
1069 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h new file mode 100644 index 000000000000..d8612a378345 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_video.h | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * vsp1_video.h -- R-Car VSP1 Video Node | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | #ifndef __VSP1_VIDEO_H__ | ||
14 | #define __VSP1_VIDEO_H__ | ||
15 | |||
16 | #include <linux/list.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/wait.h> | ||
19 | |||
20 | #include <media/media-entity.h> | ||
21 | #include <media/videobuf2-core.h> | ||
22 | |||
23 | struct vsp1_video; | ||
24 | |||
25 | /* | ||
26 | * struct vsp1_format_info - VSP1 video format description | ||
27 | * @mbus: media bus format code | ||
28 | * @fourcc: V4L2 pixel format FCC identifier | ||
29 | * @planes: number of planes | ||
30 | * @bpp: bits per pixel | ||
31 | * @hwfmt: VSP1 hardware format | ||
32 | * @swap_yc: the Y and C components are swapped (Y comes before C) | ||
33 | * @swap_uv: the U and V components are swapped (V comes before U) | ||
34 | * @hsub: horizontal subsampling factor | ||
35 | * @vsub: vertical subsampling factor | ||
36 | */ | ||
37 | struct vsp1_format_info { | ||
38 | u32 fourcc; | ||
39 | unsigned int mbus; | ||
40 | unsigned int hwfmt; | ||
41 | unsigned int swap; | ||
42 | unsigned int planes; | ||
43 | unsigned int bpp[3]; | ||
44 | bool swap_yc; | ||
45 | bool swap_uv; | ||
46 | unsigned int hsub; | ||
47 | unsigned int vsub; | ||
48 | }; | ||
49 | |||
50 | enum vsp1_pipeline_state { | ||
51 | VSP1_PIPELINE_STOPPED, | ||
52 | VSP1_PIPELINE_RUNNING, | ||
53 | VSP1_PIPELINE_STOPPING, | ||
54 | }; | ||
55 | |||
56 | /* | ||
57 | * struct vsp1_pipeline - A VSP1 hardware pipeline | ||
58 | * @media: the media pipeline | ||
59 | * @irqlock: protects the pipeline state | ||
60 | * @lock: protects the pipeline use count and stream count | ||
61 | */ | ||
62 | struct vsp1_pipeline { | ||
63 | struct media_pipeline pipe; | ||
64 | |||
65 | spinlock_t irqlock; | ||
66 | enum vsp1_pipeline_state state; | ||
67 | wait_queue_head_t wq; | ||
68 | |||
69 | struct mutex lock; | ||
70 | unsigned int use_count; | ||
71 | unsigned int stream_count; | ||
72 | unsigned int buffers_ready; | ||
73 | |||
74 | unsigned int num_video; | ||
75 | unsigned int num_inputs; | ||
76 | struct vsp1_rwpf *inputs[VPS1_MAX_RPF]; | ||
77 | struct vsp1_rwpf *output; | ||
78 | struct vsp1_entity *lif; | ||
79 | |||
80 | struct list_head entities; | ||
81 | }; | ||
82 | |||
83 | static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) | ||
84 | { | ||
85 | if (likely(e->pipe)) | ||
86 | return container_of(e->pipe, struct vsp1_pipeline, pipe); | ||
87 | else | ||
88 | return NULL; | ||
89 | } | ||
90 | |||
91 | struct vsp1_video_buffer { | ||
92 | struct vsp1_video *video; | ||
93 | struct vb2_buffer buf; | ||
94 | struct list_head queue; | ||
95 | |||
96 | dma_addr_t addr[3]; | ||
97 | unsigned int length[3]; | ||
98 | }; | ||
99 | |||
100 | static inline struct vsp1_video_buffer * | ||
101 | to_vsp1_video_buffer(struct vb2_buffer *vb) | ||
102 | { | ||
103 | return container_of(vb, struct vsp1_video_buffer, buf); | ||
104 | } | ||
105 | |||
106 | struct vsp1_video_operations { | ||
107 | void (*queue)(struct vsp1_video *video, struct vsp1_video_buffer *buf); | ||
108 | }; | ||
109 | |||
110 | struct vsp1_video { | ||
111 | struct vsp1_device *vsp1; | ||
112 | struct vsp1_entity *rwpf; | ||
113 | |||
114 | const struct vsp1_video_operations *ops; | ||
115 | |||
116 | struct video_device video; | ||
117 | enum v4l2_buf_type type; | ||
118 | struct media_pad pad; | ||
119 | |||
120 | struct mutex lock; | ||
121 | struct v4l2_pix_format_mplane format; | ||
122 | const struct vsp1_format_info *fmtinfo; | ||
123 | |||
124 | struct vsp1_pipeline pipe; | ||
125 | unsigned int pipe_index; | ||
126 | |||
127 | struct vb2_queue queue; | ||
128 | void *alloc_ctx; | ||
129 | spinlock_t irqlock; | ||
130 | struct list_head irqqueue; | ||
131 | unsigned int sequence; | ||
132 | }; | ||
133 | |||
134 | static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev) | ||
135 | { | ||
136 | return container_of(vdev, struct vsp1_video, video); | ||
137 | } | ||
138 | |||
139 | int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf); | ||
140 | void vsp1_video_cleanup(struct vsp1_video *video); | ||
141 | |||
142 | void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); | ||
143 | |||
144 | #endif /* __VSP1_VIDEO_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c new file mode 100644 index 000000000000..db4b85ee05fc --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_wpf.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * vsp1_wpf.c -- R-Car VSP1 Write Pixel Formatter | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Corporation | ||
5 | * | ||
6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | |||
16 | #include <media/v4l2-subdev.h> | ||
17 | |||
18 | #include "vsp1.h" | ||
19 | #include "vsp1_rwpf.h" | ||
20 | #include "vsp1_video.h" | ||
21 | |||
22 | #define WPF_MAX_WIDTH 2048 | ||
23 | #define WPF_MAX_HEIGHT 2048 | ||
24 | |||
25 | /* ----------------------------------------------------------------------------- | ||
26 | * Device Access | ||
27 | */ | ||
28 | |||
29 | static inline u32 vsp1_wpf_read(struct vsp1_rwpf *wpf, u32 reg) | ||
30 | { | ||
31 | return vsp1_read(wpf->entity.vsp1, | ||
32 | reg + wpf->entity.index * VI6_WPF_OFFSET); | ||
33 | } | ||
34 | |||
35 | static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data) | ||
36 | { | ||
37 | vsp1_write(wpf->entity.vsp1, | ||
38 | reg + wpf->entity.index * VI6_WPF_OFFSET, data); | ||
39 | } | ||
40 | |||
41 | /* ----------------------------------------------------------------------------- | ||
42 | * V4L2 Subdevice Core Operations | ||
43 | */ | ||
44 | |||
45 | static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) | ||
46 | { | ||
47 | struct vsp1_rwpf *wpf = to_rwpf(subdev); | ||
48 | struct vsp1_pipeline *pipe = | ||
49 | to_vsp1_pipeline(&wpf->entity.subdev.entity); | ||
50 | struct vsp1_device *vsp1 = wpf->entity.vsp1; | ||
51 | const struct v4l2_mbus_framefmt *format = | ||
52 | &wpf->entity.formats[RWPF_PAD_SOURCE]; | ||
53 | unsigned int i; | ||
54 | u32 srcrpf = 0; | ||
55 | u32 outfmt = 0; | ||
56 | |||
57 | if (!enable) { | ||
58 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | /* Sources */ | ||
63 | for (i = 0; i < pipe->num_inputs; ++i) { | ||
64 | struct vsp1_rwpf *input = pipe->inputs[i]; | ||
65 | |||
66 | srcrpf |= VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index); | ||
67 | } | ||
68 | |||
69 | vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); | ||
70 | |||
71 | /* Destination stride. Cropping isn't supported yet. */ | ||
72 | if (!pipe->lif) { | ||
73 | struct v4l2_pix_format_mplane *format = &wpf->video.format; | ||
74 | |||
75 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y, | ||
76 | format->plane_fmt[0].bytesperline); | ||
77 | if (format->num_planes > 1) | ||
78 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_C, | ||
79 | format->plane_fmt[1].bytesperline); | ||
80 | } | ||
81 | |||
82 | vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, | ||
83 | format->width << VI6_WPF_SZCLIP_SIZE_SHIFT); | ||
84 | vsp1_wpf_write(wpf, VI6_WPF_VSZCLIP, | ||
85 | format->height << VI6_WPF_SZCLIP_SIZE_SHIFT); | ||
86 | |||
87 | /* Format */ | ||
88 | if (!pipe->lif) { | ||
89 | const struct vsp1_format_info *fmtinfo = wpf->video.fmtinfo; | ||
90 | |||
91 | outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; | ||
92 | |||
93 | if (fmtinfo->swap_yc) | ||
94 | outfmt |= VI6_WPF_OUTFMT_SPYCS; | ||
95 | if (fmtinfo->swap_uv) | ||
96 | outfmt |= VI6_WPF_OUTFMT_SPUVS; | ||
97 | |||
98 | vsp1_wpf_write(wpf, VI6_WPF_DSWAP, fmtinfo->swap); | ||
99 | } | ||
100 | |||
101 | if (wpf->entity.formats[RWPF_PAD_SINK].code != | ||
102 | wpf->entity.formats[RWPF_PAD_SOURCE].code) | ||
103 | outfmt |= VI6_WPF_OUTFMT_CSC; | ||
104 | |||
105 | vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); | ||
106 | |||
107 | vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index), | ||
108 | VI6_DPR_WPF_FPORCH_FP_WPFN); | ||
109 | |||
110 | vsp1_write(vsp1, VI6_WPF_WRBCK_CTRL, 0); | ||
111 | |||
112 | /* Enable interrupts */ | ||
113 | vsp1_write(vsp1, VI6_WPF_IRQ_STA(wpf->entity.index), 0); | ||
114 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), | ||
115 | VI6_WFP_IRQ_ENB_FREE); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | /* ----------------------------------------------------------------------------- | ||
121 | * V4L2 Subdevice Operations | ||
122 | */ | ||
123 | |||
124 | static struct v4l2_subdev_video_ops wpf_video_ops = { | ||
125 | .s_stream = wpf_s_stream, | ||
126 | }; | ||
127 | |||
128 | static struct v4l2_subdev_pad_ops wpf_pad_ops = { | ||
129 | .enum_mbus_code = vsp1_rwpf_enum_mbus_code, | ||
130 | .enum_frame_size = vsp1_rwpf_enum_frame_size, | ||
131 | .get_fmt = vsp1_rwpf_get_format, | ||
132 | .set_fmt = vsp1_rwpf_set_format, | ||
133 | }; | ||
134 | |||
135 | static struct v4l2_subdev_ops wpf_ops = { | ||
136 | .video = &wpf_video_ops, | ||
137 | .pad = &wpf_pad_ops, | ||
138 | }; | ||
139 | |||
140 | /* ----------------------------------------------------------------------------- | ||
141 | * Video Device Operations | ||
142 | */ | ||
143 | |||
144 | static void wpf_vdev_queue(struct vsp1_video *video, | ||
145 | struct vsp1_video_buffer *buf) | ||
146 | { | ||
147 | struct vsp1_rwpf *wpf = container_of(video, struct vsp1_rwpf, video); | ||
148 | |||
149 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]); | ||
150 | if (buf->buf.num_planes > 1) | ||
151 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, buf->addr[1]); | ||
152 | if (buf->buf.num_planes > 2) | ||
153 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, buf->addr[2]); | ||
154 | } | ||
155 | |||
156 | static const struct vsp1_video_operations wpf_vdev_ops = { | ||
157 | .queue = wpf_vdev_queue, | ||
158 | }; | ||
159 | |||
160 | /* ----------------------------------------------------------------------------- | ||
161 | * Initialization and Cleanup | ||
162 | */ | ||
163 | |||
164 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | ||
165 | { | ||
166 | struct v4l2_subdev *subdev; | ||
167 | struct vsp1_video *video; | ||
168 | struct vsp1_rwpf *wpf; | ||
169 | unsigned int flags; | ||
170 | int ret; | ||
171 | |||
172 | wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); | ||
173 | if (wpf == NULL) | ||
174 | return ERR_PTR(-ENOMEM); | ||
175 | |||
176 | wpf->max_width = WPF_MAX_WIDTH; | ||
177 | wpf->max_height = WPF_MAX_HEIGHT; | ||
178 | |||
179 | wpf->entity.type = VSP1_ENTITY_WPF; | ||
180 | wpf->entity.index = index; | ||
181 | wpf->entity.id = VI6_DPR_NODE_WPF(index); | ||
182 | |||
183 | ret = vsp1_entity_init(vsp1, &wpf->entity, 2); | ||
184 | if (ret < 0) | ||
185 | return ERR_PTR(ret); | ||
186 | |||
187 | /* Initialize the V4L2 subdev. */ | ||
188 | subdev = &wpf->entity.subdev; | ||
189 | v4l2_subdev_init(subdev, &wpf_ops); | ||
190 | |||
191 | subdev->entity.ops = &vsp1_media_ops; | ||
192 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
193 | snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u", | ||
194 | dev_name(vsp1->dev), index); | ||
195 | v4l2_set_subdevdata(subdev, wpf); | ||
196 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
197 | |||
198 | vsp1_entity_init_formats(subdev, NULL); | ||
199 | |||
200 | /* Initialize the video device. */ | ||
201 | video = &wpf->video; | ||
202 | |||
203 | video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | ||
204 | video->vsp1 = vsp1; | ||
205 | video->ops = &wpf_vdev_ops; | ||
206 | |||
207 | ret = vsp1_video_init(video, &wpf->entity); | ||
208 | if (ret < 0) | ||
209 | goto error_video; | ||
210 | |||
211 | /* Connect the video device to the WPF. All connections are immutable | ||
212 | * except for the WPF0 source link if a LIF is present. | ||
213 | */ | ||
214 | flags = MEDIA_LNK_FL_ENABLED; | ||
215 | if (!(vsp1->pdata->features & VSP1_HAS_LIF) || index != 0) | ||
216 | flags |= MEDIA_LNK_FL_IMMUTABLE; | ||
217 | |||
218 | ret = media_entity_create_link(&wpf->entity.subdev.entity, | ||
219 | RWPF_PAD_SOURCE, | ||
220 | &wpf->video.video.entity, 0, flags); | ||
221 | if (ret < 0) | ||
222 | goto error_link; | ||
223 | |||
224 | wpf->entity.sink = &wpf->video.video.entity; | ||
225 | |||
226 | return wpf; | ||
227 | |||
228 | error_link: | ||
229 | vsp1_video_cleanup(video); | ||
230 | error_video: | ||
231 | media_entity_cleanup(&wpf->entity.subdev.entity); | ||
232 | return ERR_PTR(ret); | ||
233 | } | ||
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index d529ba788f41..39882ddd2594 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
@@ -12,6 +12,9 @@ menuconfig RADIO_ADAPTERS | |||
12 | 12 | ||
13 | if RADIO_ADAPTERS && VIDEO_V4L2 | 13 | if RADIO_ADAPTERS && VIDEO_V4L2 |
14 | 14 | ||
15 | config RADIO_TEA575X | ||
16 | tristate | ||
17 | |||
15 | config RADIO_SI470X | 18 | config RADIO_SI470X |
16 | bool "Silicon Labs Si470x FM Radio Receiver support" | 19 | bool "Silicon Labs Si470x FM Radio Receiver support" |
17 | depends on VIDEO_V4L2 | 20 | depends on VIDEO_V4L2 |
@@ -61,7 +64,8 @@ config USB_DSBR | |||
61 | 64 | ||
62 | config RADIO_MAXIRADIO | 65 | config RADIO_MAXIRADIO |
63 | tristate "Guillemot MAXI Radio FM 2000 radio" | 66 | tristate "Guillemot MAXI Radio FM 2000 radio" |
64 | depends on VIDEO_V4L2 && PCI && SND | 67 | depends on VIDEO_V4L2 && PCI |
68 | select RADIO_TEA575X | ||
65 | ---help--- | 69 | ---help--- |
66 | Choose Y here if you have this radio card. This card may also be | 70 | Choose Y here if you have this radio card. This card may also be |
67 | found as Gemtek PCI FM. | 71 | found as Gemtek PCI FM. |
@@ -76,7 +80,8 @@ config RADIO_MAXIRADIO | |||
76 | 80 | ||
77 | config RADIO_SHARK | 81 | config RADIO_SHARK |
78 | tristate "Griffin radioSHARK USB radio receiver" | 82 | tristate "Griffin radioSHARK USB radio receiver" |
79 | depends on USB && SND | 83 | depends on USB |
84 | select RADIO_TEA575X | ||
80 | ---help--- | 85 | ---help--- |
81 | Choose Y here if you have this radio receiver. | 86 | Choose Y here if you have this radio receiver. |
82 | 87 | ||
@@ -393,7 +398,8 @@ config RADIO_SF16FMI | |||
393 | 398 | ||
394 | config RADIO_SF16FMR2 | 399 | config RADIO_SF16FMR2 |
395 | tristate "SF16-FMR2/SF16-FMD2 Radio" | 400 | tristate "SF16-FMR2/SF16-FMD2 Radio" |
396 | depends on ISA && VIDEO_V4L2 && SND | 401 | depends on ISA && VIDEO_V4L2 |
402 | select RADIO_TEA575X | ||
397 | ---help--- | 403 | ---help--- |
398 | Choose Y here if you have one of these FM radio cards. | 404 | Choose Y here if you have one of these FM radio cards. |
399 | 405 | ||
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 0dcdb320cfc7..3b645601800d 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile | |||
@@ -32,6 +32,7 @@ obj-$(CONFIG_RADIO_TEF6862) += tef6862.o | |||
32 | obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o | 32 | obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o |
33 | obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o | 33 | obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o |
34 | obj-$(CONFIG_RADIO_WL128X) += wl128x/ | 34 | obj-$(CONFIG_RADIO_WL128X) += wl128x/ |
35 | obj-$(CONFIG_RADIO_TEA575X) += tea575x.o | ||
35 | 36 | ||
36 | shark2-objs := radio-shark2.o radio-tea5777.o | 37 | shark2-objs := radio-shark2.o radio-tea5777.o |
37 | 38 | ||
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 177bcbd7a7c1..705dd6f9162c 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <media/v4l2-ioctl.h> | 26 | #include <media/v4l2-ioctl.h> |
27 | #include <media/v4l2-ctrls.h> | 27 | #include <media/v4l2-ctrls.h> |
28 | #include "radio-isa.h" | 28 | #include "radio-isa.h" |
29 | #include "lm7000.h" | ||
29 | 30 | ||
30 | MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); | 31 | MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); |
31 | MODULE_DESCRIPTION("A driver for the Aztech radio card."); | 32 | MODULE_DESCRIPTION("A driver for the Aztech radio card."); |
@@ -54,18 +55,29 @@ struct aztech { | |||
54 | int curvol; | 55 | int curvol; |
55 | }; | 56 | }; |
56 | 57 | ||
57 | static void send_0_byte(struct aztech *az) | 58 | /* bit definitions for register read */ |
58 | { | 59 | #define AZTECH_BIT_NOT_TUNED (1 << 0) |
59 | udelay(radio_wait_time); | 60 | #define AZTECH_BIT_MONO (1 << 1) |
60 | outb_p(2 + az->curvol, az->isa.io); | 61 | /* bit definitions for register write */ |
61 | outb_p(64 + 2 + az->curvol, az->isa.io); | 62 | #define AZTECH_BIT_TUN_CE (1 << 1) |
62 | } | 63 | #define AZTECH_BIT_TUN_CLK (1 << 6) |
64 | #define AZTECH_BIT_TUN_DATA (1 << 7) | ||
65 | /* bits 0 and 2 are volume control, bits 3..5 are not connected */ | ||
63 | 66 | ||
64 | static void send_1_byte(struct aztech *az) | 67 | static void aztech_set_pins(void *handle, u8 pins) |
65 | { | 68 | { |
66 | udelay(radio_wait_time); | 69 | struct radio_isa_card *isa = handle; |
67 | outb_p(128 + 2 + az->curvol, az->isa.io); | 70 | struct aztech *az = container_of(isa, struct aztech, isa); |
68 | outb_p(128 + 64 + 2 + az->curvol, az->isa.io); | 71 | u8 bits = az->curvol; |
72 | |||
73 | if (pins & LM7000_DATA) | ||
74 | bits |= AZTECH_BIT_TUN_DATA; | ||
75 | if (pins & LM7000_CLK) | ||
76 | bits |= AZTECH_BIT_TUN_CLK; | ||
77 | if (pins & LM7000_CE) | ||
78 | bits |= AZTECH_BIT_TUN_CE; | ||
79 | |||
80 | outb_p(bits, az->isa.io); | ||
69 | } | 81 | } |
70 | 82 | ||
71 | static struct radio_isa_card *aztech_alloc(void) | 83 | static struct radio_isa_card *aztech_alloc(void) |
@@ -77,58 +89,21 @@ static struct radio_isa_card *aztech_alloc(void) | |||
77 | 89 | ||
78 | static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq) | 90 | static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq) |
79 | { | 91 | { |
80 | struct aztech *az = container_of(isa, struct aztech, isa); | 92 | lm7000_set_freq(freq, isa, aztech_set_pins); |
81 | int i; | ||
82 | |||
83 | freq += 171200; /* Add 10.7 MHz IF */ | ||
84 | freq /= 800; /* Convert to 50 kHz units */ | ||
85 | |||
86 | send_0_byte(az); /* 0: LSB of frequency */ | ||
87 | |||
88 | for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ | ||
89 | if (freq & (1 << i)) | ||
90 | send_1_byte(az); | ||
91 | else | ||
92 | send_0_byte(az); | ||
93 | |||
94 | send_0_byte(az); /* 14: test bit - always 0 */ | ||
95 | send_0_byte(az); /* 15: test bit - always 0 */ | ||
96 | send_0_byte(az); /* 16: band data 0 - always 0 */ | ||
97 | if (isa->stereo) /* 17: stereo (1 to enable) */ | ||
98 | send_1_byte(az); | ||
99 | else | ||
100 | send_0_byte(az); | ||
101 | |||
102 | send_1_byte(az); /* 18: band data 1 - unknown */ | ||
103 | send_0_byte(az); /* 19: time base - always 0 */ | ||
104 | send_0_byte(az); /* 20: spacing (0 = 25 kHz) */ | ||
105 | send_1_byte(az); /* 21: spacing (1 = 25 kHz) */ | ||
106 | send_0_byte(az); /* 22: spacing (0 = 25 kHz) */ | ||
107 | send_1_byte(az); /* 23: AM/FM (FM = 1, always) */ | ||
108 | |||
109 | /* latch frequency */ | ||
110 | |||
111 | udelay(radio_wait_time); | ||
112 | outb_p(128 + 64 + az->curvol, az->isa.io); | ||
113 | 93 | ||
114 | return 0; | 94 | return 0; |
115 | } | 95 | } |
116 | 96 | ||
117 | /* thanks to Michael Dwyer for giving me a dose of clues in | ||
118 | * the signal strength department.. | ||
119 | * | ||
120 | * This card has a stereo bit - bit 0 set = mono, not set = stereo | ||
121 | */ | ||
122 | static u32 aztech_g_rxsubchans(struct radio_isa_card *isa) | 97 | static u32 aztech_g_rxsubchans(struct radio_isa_card *isa) |
123 | { | 98 | { |
124 | if (inb(isa->io) & 1) | 99 | if (inb(isa->io) & AZTECH_BIT_MONO) |
125 | return V4L2_TUNER_SUB_MONO; | 100 | return V4L2_TUNER_SUB_MONO; |
126 | return V4L2_TUNER_SUB_STEREO; | 101 | return V4L2_TUNER_SUB_STEREO; |
127 | } | 102 | } |
128 | 103 | ||
129 | static int aztech_s_stereo(struct radio_isa_card *isa, bool stereo) | 104 | static u32 aztech_g_signal(struct radio_isa_card *isa) |
130 | { | 105 | { |
131 | return aztech_s_frequency(isa, isa->freq); | 106 | return (inb(isa->io) & AZTECH_BIT_NOT_TUNED) ? 0 : 0xffff; |
132 | } | 107 | } |
133 | 108 | ||
134 | static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) | 109 | static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) |
@@ -146,8 +121,8 @@ static const struct radio_isa_ops aztech_ops = { | |||
146 | .alloc = aztech_alloc, | 121 | .alloc = aztech_alloc, |
147 | .s_mute_volume = aztech_s_mute_volume, | 122 | .s_mute_volume = aztech_s_mute_volume, |
148 | .s_frequency = aztech_s_frequency, | 123 | .s_frequency = aztech_s_frequency, |
149 | .s_stereo = aztech_s_stereo, | ||
150 | .g_rxsubchans = aztech_g_rxsubchans, | 124 | .g_rxsubchans = aztech_g_rxsubchans, |
125 | .g_signal = aztech_g_signal, | ||
151 | }; | 126 | }; |
152 | 127 | ||
153 | static const int aztech_ioports[] = { 0x350, 0x358 }; | 128 | static const int aztech_ioports[] = { 0x350, 0x358 }; |
@@ -165,7 +140,7 @@ static struct radio_isa_driver aztech_driver = { | |||
165 | .radio_nr_params = radio_nr, | 140 | .radio_nr_params = radio_nr, |
166 | .io_ports = aztech_ioports, | 141 | .io_ports = aztech_ioports, |
167 | .num_of_io_ports = ARRAY_SIZE(aztech_ioports), | 142 | .num_of_io_ports = ARRAY_SIZE(aztech_ioports), |
168 | .region_size = 2, | 143 | .region_size = 8, |
169 | .card = "Aztech Radio", | 144 | .card = "Aztech Radio", |
170 | .ops = &aztech_ops, | 145 | .ops = &aztech_ops, |
171 | .has_stereo = true, | 146 | .has_stereo = true, |
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index bd4d3a7cdadd..5236035f0f2a 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include <linux/videodev2.h> | 42 | #include <linux/videodev2.h> |
43 | #include <linux/io.h> | 43 | #include <linux/io.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <sound/tea575x-tuner.h> | 45 | #include <media/tea575x.h> |
46 | #include <media/v4l2-device.h> | 46 | #include <media/v4l2-device.h> |
47 | #include <media/v4l2-ioctl.h> | 47 | #include <media/v4l2-ioctl.h> |
48 | #include <media/v4l2-fh.h> | 48 | #include <media/v4l2-fh.h> |
@@ -200,15 +200,4 @@ static struct pci_driver maxiradio_driver = { | |||
200 | .remove = maxiradio_remove, | 200 | .remove = maxiradio_remove, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | static int __init maxiradio_init(void) | 203 | module_pci_driver(maxiradio_driver); |
204 | { | ||
205 | return pci_register_driver(&maxiradio_driver); | ||
206 | } | ||
207 | |||
208 | static void __exit maxiradio_exit(void) | ||
209 | { | ||
210 | pci_unregister_driver(&maxiradio_driver); | ||
211 | } | ||
212 | |||
213 | module_init(maxiradio_init); | ||
214 | module_exit(maxiradio_exit); | ||
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 9c0990457a7c..f1e3714b5f16 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/io.h> /* outb, outb_p */ | 14 | #include <linux/io.h> /* outb, outb_p */ |
15 | #include <linux/isa.h> | 15 | #include <linux/isa.h> |
16 | #include <linux/pnp.h> | 16 | #include <linux/pnp.h> |
17 | #include <sound/tea575x-tuner.h> | 17 | #include <media/tea575x.h> |
18 | 18 | ||
19 | MODULE_AUTHOR("Ondrej Zary"); | 19 | MODULE_AUTHOR("Ondrej Zary"); |
20 | MODULE_DESCRIPTION("MediaForte SF16-FMR2 and SF16-FMD2 FM radio card driver"); | 20 | MODULE_DESCRIPTION("MediaForte SF16-FMR2 and SF16-FMD2 FM radio card driver"); |
diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 8fa18ab5b725..b91477212413 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
34 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
35 | #include <media/v4l2-device.h> | 35 | #include <media/v4l2-device.h> |
36 | #include <sound/tea575x-tuner.h> | 36 | #include <media/tea575x.h> |
37 | 37 | ||
38 | #if defined(CONFIG_LEDS_CLASS) || \ | 38 | #if defined(CONFIG_LEDS_CLASS) || \ |
39 | (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) | 39 | (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) |
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 62f3edec39bc..d6d4d60261d5 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c | |||
@@ -142,8 +142,6 @@ MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); | |||
142 | /************************************************************************** | 142 | /************************************************************************** |
143 | * Software/Hardware Versions from Scratch Page | 143 | * Software/Hardware Versions from Scratch Page |
144 | **************************************************************************/ | 144 | **************************************************************************/ |
145 | #define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6 | ||
146 | #define RADIO_SW_VERSION 1 | ||
147 | #define RADIO_HW_VERSION 1 | 145 | #define RADIO_HW_VERSION 1 |
148 | 146 | ||
149 | 147 | ||
@@ -682,15 +680,6 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, | |||
682 | } | 680 | } |
683 | dev_info(&intf->dev, "software version %d, hardware version %d\n", | 681 | dev_info(&intf->dev, "software version %d, hardware version %d\n", |
684 | radio->software_version, radio->hardware_version); | 682 | radio->software_version, radio->hardware_version); |
685 | if (radio->software_version < RADIO_SW_VERSION) { | ||
686 | dev_warn(&intf->dev, | ||
687 | "This driver is known to work with " | ||
688 | "software version %hu,\n", RADIO_SW_VERSION); | ||
689 | dev_warn(&intf->dev, | ||
690 | "but the device has software version %hu.\n", | ||
691 | radio->software_version); | ||
692 | version_warning = 1; | ||
693 | } | ||
694 | if (radio->hardware_version < RADIO_HW_VERSION) { | 683 | if (radio->hardware_version < RADIO_HW_VERSION) { |
695 | dev_warn(&intf->dev, | 684 | dev_warn(&intf->dev, |
696 | "This driver is known to work with " | 685 | "This driver is known to work with " |
diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c new file mode 100644 index 000000000000..cef06981b7c9 --- /dev/null +++ b/drivers/media/radio/tea575x.c | |||
@@ -0,0 +1,584 @@ | |||
1 | /* | ||
2 | * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips | ||
3 | * | ||
4 | * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz> | ||
5 | * | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <asm/io.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <media/v4l2-device.h> | ||
30 | #include <media/v4l2-dev.h> | ||
31 | #include <media/v4l2-fh.h> | ||
32 | #include <media/v4l2-ioctl.h> | ||
33 | #include <media/v4l2-event.h> | ||
34 | #include <media/tea575x.h> | ||
35 | |||
36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
37 | MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | /* | ||
41 | * definitions | ||
42 | */ | ||
43 | |||
44 | #define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ | ||
45 | #define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ | ||
46 | #define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ | ||
47 | #define TEA575X_BIT_BAND_MASK (3<<20) | ||
48 | #define TEA575X_BIT_BAND_FM (0<<20) | ||
49 | #define TEA575X_BIT_BAND_MW (1<<20) | ||
50 | #define TEA575X_BIT_BAND_LW (2<<20) | ||
51 | #define TEA575X_BIT_BAND_SW (3<<20) | ||
52 | #define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ | ||
53 | #define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ | ||
54 | #define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ | ||
55 | #define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ | ||
56 | #define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ | ||
57 | #define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ | ||
58 | #define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ | ||
59 | #define TEA575X_BIT_DUMMY (1<<15) /* buffer */ | ||
60 | #define TEA575X_BIT_FREQ_MASK 0x7fff | ||
61 | |||
62 | enum { BAND_FM, BAND_FM_JAPAN, BAND_AM }; | ||
63 | |||
64 | static const struct v4l2_frequency_band bands[] = { | ||
65 | { | ||
66 | .type = V4L2_TUNER_RADIO, | ||
67 | .index = 0, | ||
68 | .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | | ||
69 | V4L2_TUNER_CAP_FREQ_BANDS, | ||
70 | .rangelow = 87500 * 16, | ||
71 | .rangehigh = 108000 * 16, | ||
72 | .modulation = V4L2_BAND_MODULATION_FM, | ||
73 | }, | ||
74 | { | ||
75 | .type = V4L2_TUNER_RADIO, | ||
76 | .index = 0, | ||
77 | .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | | ||
78 | V4L2_TUNER_CAP_FREQ_BANDS, | ||
79 | .rangelow = 76000 * 16, | ||
80 | .rangehigh = 91000 * 16, | ||
81 | .modulation = V4L2_BAND_MODULATION_FM, | ||
82 | }, | ||
83 | { | ||
84 | .type = V4L2_TUNER_RADIO, | ||
85 | .index = 1, | ||
86 | .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, | ||
87 | .rangelow = 530 * 16, | ||
88 | .rangehigh = 1710 * 16, | ||
89 | .modulation = V4L2_BAND_MODULATION_AM, | ||
90 | }, | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * lowlevel part | ||
95 | */ | ||
96 | |||
97 | static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) | ||
98 | { | ||
99 | u16 l; | ||
100 | u8 data; | ||
101 | |||
102 | if (tea->ops->write_val) | ||
103 | return tea->ops->write_val(tea, val); | ||
104 | |||
105 | tea->ops->set_direction(tea, 1); | ||
106 | udelay(16); | ||
107 | |||
108 | for (l = 25; l > 0; l--) { | ||
109 | data = (val >> 24) & TEA575X_DATA; | ||
110 | val <<= 1; /* shift data */ | ||
111 | tea->ops->set_pins(tea, data | TEA575X_WREN); | ||
112 | udelay(2); | ||
113 | tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK); | ||
114 | udelay(2); | ||
115 | tea->ops->set_pins(tea, data | TEA575X_WREN); | ||
116 | udelay(2); | ||
117 | } | ||
118 | |||
119 | if (!tea->mute) | ||
120 | tea->ops->set_pins(tea, 0); | ||
121 | } | ||
122 | |||
123 | static u32 snd_tea575x_read(struct snd_tea575x *tea) | ||
124 | { | ||
125 | u16 l, rdata; | ||
126 | u32 data = 0; | ||
127 | |||
128 | if (tea->ops->read_val) | ||
129 | return tea->ops->read_val(tea); | ||
130 | |||
131 | tea->ops->set_direction(tea, 0); | ||
132 | tea->ops->set_pins(tea, 0); | ||
133 | udelay(16); | ||
134 | |||
135 | for (l = 24; l--;) { | ||
136 | tea->ops->set_pins(tea, TEA575X_CLK); | ||
137 | udelay(2); | ||
138 | if (!l) | ||
139 | tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1; | ||
140 | tea->ops->set_pins(tea, 0); | ||
141 | udelay(2); | ||
142 | data <<= 1; /* shift data */ | ||
143 | rdata = tea->ops->get_pins(tea); | ||
144 | if (!l) | ||
145 | tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1; | ||
146 | if (rdata & TEA575X_DATA) | ||
147 | data++; | ||
148 | udelay(2); | ||
149 | } | ||
150 | |||
151 | if (tea->mute) | ||
152 | tea->ops->set_pins(tea, TEA575X_WREN); | ||
153 | |||
154 | return data; | ||
155 | } | ||
156 | |||
157 | static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) | ||
158 | { | ||
159 | u32 freq = val & TEA575X_BIT_FREQ_MASK; | ||
160 | |||
161 | if (freq == 0) | ||
162 | return freq; | ||
163 | |||
164 | switch (tea->band) { | ||
165 | case BAND_FM: | ||
166 | /* freq *= 12.5 */ | ||
167 | freq *= 125; | ||
168 | freq /= 10; | ||
169 | /* crystal fixup */ | ||
170 | freq -= TEA575X_FMIF; | ||
171 | break; | ||
172 | case BAND_FM_JAPAN: | ||
173 | /* freq *= 12.5 */ | ||
174 | freq *= 125; | ||
175 | freq /= 10; | ||
176 | /* crystal fixup */ | ||
177 | freq += TEA575X_FMIF; | ||
178 | break; | ||
179 | case BAND_AM: | ||
180 | /* crystal fixup */ | ||
181 | freq -= TEA575X_AMIF; | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | return clamp(freq * 16, bands[tea->band].rangelow, | ||
186 | bands[tea->band].rangehigh); /* from kHz */ | ||
187 | } | ||
188 | |||
189 | static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) | ||
190 | { | ||
191 | return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea)); | ||
192 | } | ||
193 | |||
194 | void snd_tea575x_set_freq(struct snd_tea575x *tea) | ||
195 | { | ||
196 | u32 freq = tea->freq / 16; /* to kHz */ | ||
197 | u32 band = 0; | ||
198 | |||
199 | switch (tea->band) { | ||
200 | case BAND_FM: | ||
201 | band = TEA575X_BIT_BAND_FM; | ||
202 | /* crystal fixup */ | ||
203 | freq += TEA575X_FMIF; | ||
204 | /* freq /= 12.5 */ | ||
205 | freq *= 10; | ||
206 | freq /= 125; | ||
207 | break; | ||
208 | case BAND_FM_JAPAN: | ||
209 | band = TEA575X_BIT_BAND_FM; | ||
210 | /* crystal fixup */ | ||
211 | freq -= TEA575X_FMIF; | ||
212 | /* freq /= 12.5 */ | ||
213 | freq *= 10; | ||
214 | freq /= 125; | ||
215 | break; | ||
216 | case BAND_AM: | ||
217 | band = TEA575X_BIT_BAND_MW; | ||
218 | /* crystal fixup */ | ||
219 | freq += TEA575X_AMIF; | ||
220 | break; | ||
221 | } | ||
222 | |||
223 | tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK); | ||
224 | tea->val |= band; | ||
225 | tea->val |= freq & TEA575X_BIT_FREQ_MASK; | ||
226 | snd_tea575x_write(tea, tea->val); | ||
227 | tea->freq = snd_tea575x_val_to_freq(tea, tea->val); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * Linux Video interface | ||
232 | */ | ||
233 | |||
234 | static int vidioc_querycap(struct file *file, void *priv, | ||
235 | struct v4l2_capability *v) | ||
236 | { | ||
237 | struct snd_tea575x *tea = video_drvdata(file); | ||
238 | |||
239 | strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); | ||
240 | strlcpy(v->card, tea->card, sizeof(v->card)); | ||
241 | strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); | ||
242 | strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); | ||
243 | v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; | ||
244 | if (!tea->cannot_read_data) | ||
245 | v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; | ||
246 | v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static int vidioc_enum_freq_bands(struct file *file, void *priv, | ||
251 | struct v4l2_frequency_band *band) | ||
252 | { | ||
253 | struct snd_tea575x *tea = video_drvdata(file); | ||
254 | int index; | ||
255 | |||
256 | if (band->tuner != 0) | ||
257 | return -EINVAL; | ||
258 | |||
259 | switch (band->index) { | ||
260 | case 0: | ||
261 | if (tea->tea5759) | ||
262 | index = BAND_FM_JAPAN; | ||
263 | else | ||
264 | index = BAND_FM; | ||
265 | break; | ||
266 | case 1: | ||
267 | if (tea->has_am) { | ||
268 | index = BAND_AM; | ||
269 | break; | ||
270 | } | ||
271 | /* Fall through */ | ||
272 | default: | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | |||
276 | *band = bands[index]; | ||
277 | if (!tea->cannot_read_data) | ||
278 | band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
284 | struct v4l2_tuner *v) | ||
285 | { | ||
286 | struct snd_tea575x *tea = video_drvdata(file); | ||
287 | struct v4l2_frequency_band band_fm = { 0, }; | ||
288 | |||
289 | if (v->index > 0) | ||
290 | return -EINVAL; | ||
291 | |||
292 | snd_tea575x_read(tea); | ||
293 | vidioc_enum_freq_bands(file, priv, &band_fm); | ||
294 | |||
295 | memset(v, 0, sizeof(*v)); | ||
296 | strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); | ||
297 | v->type = V4L2_TUNER_RADIO; | ||
298 | v->capability = band_fm.capability; | ||
299 | v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow; | ||
300 | v->rangehigh = band_fm.rangehigh; | ||
301 | v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; | ||
302 | v->audmode = (tea->val & TEA575X_BIT_MONO) ? | ||
303 | V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; | ||
304 | v->signal = tea->tuned ? 0xffff : 0; | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int vidioc_s_tuner(struct file *file, void *priv, | ||
309 | const struct v4l2_tuner *v) | ||
310 | { | ||
311 | struct snd_tea575x *tea = video_drvdata(file); | ||
312 | u32 orig_val = tea->val; | ||
313 | |||
314 | if (v->index) | ||
315 | return -EINVAL; | ||
316 | tea->val &= ~TEA575X_BIT_MONO; | ||
317 | if (v->audmode == V4L2_TUNER_MODE_MONO) | ||
318 | tea->val |= TEA575X_BIT_MONO; | ||
319 | /* Only apply changes if currently tuning FM */ | ||
320 | if (tea->band != BAND_AM && tea->val != orig_val) | ||
321 | snd_tea575x_set_freq(tea); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static int vidioc_g_frequency(struct file *file, void *priv, | ||
327 | struct v4l2_frequency *f) | ||
328 | { | ||
329 | struct snd_tea575x *tea = video_drvdata(file); | ||
330 | |||
331 | if (f->tuner != 0) | ||
332 | return -EINVAL; | ||
333 | f->type = V4L2_TUNER_RADIO; | ||
334 | f->frequency = tea->freq; | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
339 | const struct v4l2_frequency *f) | ||
340 | { | ||
341 | struct snd_tea575x *tea = video_drvdata(file); | ||
342 | |||
343 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
344 | return -EINVAL; | ||
345 | |||
346 | if (tea->has_am && f->frequency < (20000 * 16)) | ||
347 | tea->band = BAND_AM; | ||
348 | else if (tea->tea5759) | ||
349 | tea->band = BAND_FM_JAPAN; | ||
350 | else | ||
351 | tea->band = BAND_FM; | ||
352 | |||
353 | tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow, | ||
354 | bands[tea->band].rangehigh); | ||
355 | snd_tea575x_set_freq(tea); | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static int vidioc_s_hw_freq_seek(struct file *file, void *fh, | ||
360 | const struct v4l2_hw_freq_seek *a) | ||
361 | { | ||
362 | struct snd_tea575x *tea = video_drvdata(file); | ||
363 | unsigned long timeout; | ||
364 | int i, spacing; | ||
365 | |||
366 | if (tea->cannot_read_data) | ||
367 | return -ENOTTY; | ||
368 | if (a->tuner || a->wrap_around) | ||
369 | return -EINVAL; | ||
370 | |||
371 | if (file->f_flags & O_NONBLOCK) | ||
372 | return -EWOULDBLOCK; | ||
373 | |||
374 | if (a->rangelow || a->rangehigh) { | ||
375 | for (i = 0; i < ARRAY_SIZE(bands); i++) { | ||
376 | if ((i == BAND_FM && tea->tea5759) || | ||
377 | (i == BAND_FM_JAPAN && !tea->tea5759) || | ||
378 | (i == BAND_AM && !tea->has_am)) | ||
379 | continue; | ||
380 | if (bands[i].rangelow == a->rangelow && | ||
381 | bands[i].rangehigh == a->rangehigh) | ||
382 | break; | ||
383 | } | ||
384 | if (i == ARRAY_SIZE(bands)) | ||
385 | return -EINVAL; /* No matching band found */ | ||
386 | if (i != tea->band) { | ||
387 | tea->band = i; | ||
388 | tea->freq = clamp(tea->freq, bands[i].rangelow, | ||
389 | bands[i].rangehigh); | ||
390 | snd_tea575x_set_freq(tea); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */ | ||
395 | |||
396 | /* clear the frequency, HW will fill it in */ | ||
397 | tea->val &= ~TEA575X_BIT_FREQ_MASK; | ||
398 | tea->val |= TEA575X_BIT_SEARCH; | ||
399 | if (a->seek_upward) | ||
400 | tea->val |= TEA575X_BIT_UPDOWN; | ||
401 | else | ||
402 | tea->val &= ~TEA575X_BIT_UPDOWN; | ||
403 | snd_tea575x_write(tea, tea->val); | ||
404 | timeout = jiffies + msecs_to_jiffies(10000); | ||
405 | for (;;) { | ||
406 | if (time_after(jiffies, timeout)) | ||
407 | break; | ||
408 | if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { | ||
409 | /* some signal arrived, stop search */ | ||
410 | tea->val &= ~TEA575X_BIT_SEARCH; | ||
411 | snd_tea575x_set_freq(tea); | ||
412 | return -ERESTARTSYS; | ||
413 | } | ||
414 | if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) { | ||
415 | u32 freq; | ||
416 | |||
417 | /* Found a frequency, wait until it can be read */ | ||
418 | for (i = 0; i < 100; i++) { | ||
419 | msleep(10); | ||
420 | freq = snd_tea575x_get_freq(tea); | ||
421 | if (freq) /* available */ | ||
422 | break; | ||
423 | } | ||
424 | if (freq == 0) /* shouldn't happen */ | ||
425 | break; | ||
426 | /* | ||
427 | * if we moved by less than the spacing, or in the | ||
428 | * wrong direction, continue seeking | ||
429 | */ | ||
430 | if (abs(tea->freq - freq) < 16 * spacing || | ||
431 | (a->seek_upward && freq < tea->freq) || | ||
432 | (!a->seek_upward && freq > tea->freq)) { | ||
433 | snd_tea575x_write(tea, tea->val); | ||
434 | continue; | ||
435 | } | ||
436 | tea->freq = freq; | ||
437 | tea->val &= ~TEA575X_BIT_SEARCH; | ||
438 | return 0; | ||
439 | } | ||
440 | } | ||
441 | tea->val &= ~TEA575X_BIT_SEARCH; | ||
442 | snd_tea575x_set_freq(tea); | ||
443 | return -ENODATA; | ||
444 | } | ||
445 | |||
446 | static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) | ||
447 | { | ||
448 | struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler); | ||
449 | |||
450 | switch (ctrl->id) { | ||
451 | case V4L2_CID_AUDIO_MUTE: | ||
452 | tea->mute = ctrl->val; | ||
453 | snd_tea575x_set_freq(tea); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | return -EINVAL; | ||
458 | } | ||
459 | |||
460 | static const struct v4l2_file_operations tea575x_fops = { | ||
461 | .unlocked_ioctl = video_ioctl2, | ||
462 | .open = v4l2_fh_open, | ||
463 | .release = v4l2_fh_release, | ||
464 | .poll = v4l2_ctrl_poll, | ||
465 | }; | ||
466 | |||
467 | static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { | ||
468 | .vidioc_querycap = vidioc_querycap, | ||
469 | .vidioc_g_tuner = vidioc_g_tuner, | ||
470 | .vidioc_s_tuner = vidioc_s_tuner, | ||
471 | .vidioc_g_frequency = vidioc_g_frequency, | ||
472 | .vidioc_s_frequency = vidioc_s_frequency, | ||
473 | .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, | ||
474 | .vidioc_enum_freq_bands = vidioc_enum_freq_bands, | ||
475 | .vidioc_log_status = v4l2_ctrl_log_status, | ||
476 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | ||
477 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
478 | }; | ||
479 | |||
480 | static const struct video_device tea575x_radio = { | ||
481 | .ioctl_ops = &tea575x_ioctl_ops, | ||
482 | .release = video_device_release_empty, | ||
483 | }; | ||
484 | |||
485 | static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { | ||
486 | .s_ctrl = tea575x_s_ctrl, | ||
487 | }; | ||
488 | |||
489 | |||
490 | int snd_tea575x_hw_init(struct snd_tea575x *tea) | ||
491 | { | ||
492 | tea->mute = true; | ||
493 | |||
494 | /* Not all devices can or know how to read the data back. | ||
495 | Such devices can set cannot_read_data to true. */ | ||
496 | if (!tea->cannot_read_data) { | ||
497 | snd_tea575x_write(tea, 0x55AA); | ||
498 | if (snd_tea575x_read(tea) != 0x55AA) | ||
499 | return -ENODEV; | ||
500 | } | ||
501 | |||
502 | tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28; | ||
503 | tea->freq = 90500 * 16; /* 90.5Mhz default */ | ||
504 | snd_tea575x_set_freq(tea); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | EXPORT_SYMBOL(snd_tea575x_hw_init); | ||
509 | |||
510 | int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) | ||
511 | { | ||
512 | int retval = snd_tea575x_hw_init(tea); | ||
513 | |||
514 | if (retval) | ||
515 | return retval; | ||
516 | |||
517 | tea->vd = tea575x_radio; | ||
518 | video_set_drvdata(&tea->vd, tea); | ||
519 | mutex_init(&tea->mutex); | ||
520 | strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); | ||
521 | tea->vd.lock = &tea->mutex; | ||
522 | tea->vd.v4l2_dev = tea->v4l2_dev; | ||
523 | tea->fops = tea575x_fops; | ||
524 | tea->fops.owner = owner; | ||
525 | tea->vd.fops = &tea->fops; | ||
526 | set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); | ||
527 | /* disable hw_freq_seek if we can't use it */ | ||
528 | if (tea->cannot_read_data) | ||
529 | v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK); | ||
530 | |||
531 | if (!tea->cannot_mute) { | ||
532 | tea->vd.ctrl_handler = &tea->ctrl_handler; | ||
533 | v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); | ||
534 | v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, | ||
535 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); | ||
536 | retval = tea->ctrl_handler.error; | ||
537 | if (retval) { | ||
538 | v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); | ||
539 | v4l2_ctrl_handler_free(&tea->ctrl_handler); | ||
540 | return retval; | ||
541 | } | ||
542 | |||
543 | if (tea->ext_init) { | ||
544 | retval = tea->ext_init(tea); | ||
545 | if (retval) { | ||
546 | v4l2_ctrl_handler_free(&tea->ctrl_handler); | ||
547 | return retval; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | v4l2_ctrl_handler_setup(&tea->ctrl_handler); | ||
552 | } | ||
553 | |||
554 | retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); | ||
555 | if (retval) { | ||
556 | v4l2_err(tea->v4l2_dev, "can't register video device!\n"); | ||
557 | v4l2_ctrl_handler_free(tea->vd.ctrl_handler); | ||
558 | return retval; | ||
559 | } | ||
560 | |||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | void snd_tea575x_exit(struct snd_tea575x *tea) | ||
565 | { | ||
566 | video_unregister_device(&tea->vd); | ||
567 | v4l2_ctrl_handler_free(tea->vd.ctrl_handler); | ||
568 | } | ||
569 | |||
570 | static int __init alsa_tea575x_module_init(void) | ||
571 | { | ||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | static void __exit alsa_tea575x_module_exit(void) | ||
576 | { | ||
577 | } | ||
578 | |||
579 | module_init(alsa_tea575x_module_init) | ||
580 | module_exit(alsa_tea575x_module_exit) | ||
581 | |||
582 | EXPORT_SYMBOL(snd_tea575x_init); | ||
583 | EXPORT_SYMBOL(snd_tea575x_exit); | ||
584 | EXPORT_SYMBOL(snd_tea575x_set_freq); | ||
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 5a79c333d45e..11e84bcc23a1 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig | |||
@@ -223,6 +223,8 @@ config IR_REDRAT3 | |||
223 | tristate "RedRat3 IR Transceiver" | 223 | tristate "RedRat3 IR Transceiver" |
224 | depends on USB_ARCH_HAS_HCD | 224 | depends on USB_ARCH_HAS_HCD |
225 | depends on RC_CORE | 225 | depends on RC_CORE |
226 | select NEW_LEDS | ||
227 | select LEDS_CLASS | ||
226 | select USB | 228 | select USB |
227 | ---help--- | 229 | ---help--- |
228 | Say Y here if you want to use a RedRat3 Infrared Transceiver. | 230 | Say Y here if you want to use a RedRat3 Infrared Transceiver. |
@@ -248,7 +250,6 @@ config IR_WINBOND_CIR | |||
248 | depends on RC_CORE | 250 | depends on RC_CORE |
249 | select NEW_LEDS | 251 | select NEW_LEDS |
250 | select LEDS_CLASS | 252 | select LEDS_CLASS |
251 | select LEDS_TRIGGERS | ||
252 | select BITREVERSE | 253 | select BITREVERSE |
253 | ---help--- | 254 | ---help--- |
254 | Say Y here if you want to use the IR remote functionality found | 255 | Say Y here if you want to use the IR remote functionality found |
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index ed184f68c17c..c1444f84717d 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c | |||
@@ -476,7 +476,7 @@ select_timeout: | |||
476 | } | 476 | } |
477 | 477 | ||
478 | /* Enable the device for receive */ | 478 | /* Enable the device for receive */ |
479 | static void ene_rx_enable(struct ene_device *dev) | 479 | static void ene_rx_enable_hw(struct ene_device *dev) |
480 | { | 480 | { |
481 | u8 reg_value; | 481 | u8 reg_value; |
482 | 482 | ||
@@ -504,11 +504,17 @@ static void ene_rx_enable(struct ene_device *dev) | |||
504 | 504 | ||
505 | /* enter idle mode */ | 505 | /* enter idle mode */ |
506 | ir_raw_event_set_idle(dev->rdev, true); | 506 | ir_raw_event_set_idle(dev->rdev, true); |
507 | } | ||
508 | |||
509 | /* Enable the device for receive - wrapper to track the state*/ | ||
510 | static void ene_rx_enable(struct ene_device *dev) | ||
511 | { | ||
512 | ene_rx_enable_hw(dev); | ||
507 | dev->rx_enabled = true; | 513 | dev->rx_enabled = true; |
508 | } | 514 | } |
509 | 515 | ||
510 | /* Disable the device receiver */ | 516 | /* Disable the device receiver */ |
511 | static void ene_rx_disable(struct ene_device *dev) | 517 | static void ene_rx_disable_hw(struct ene_device *dev) |
512 | { | 518 | { |
513 | /* disable inputs */ | 519 | /* disable inputs */ |
514 | ene_rx_enable_cir_engine(dev, false); | 520 | ene_rx_enable_cir_engine(dev, false); |
@@ -516,8 +522,13 @@ static void ene_rx_disable(struct ene_device *dev) | |||
516 | 522 | ||
517 | /* disable hardware IRQ and firmware flag */ | 523 | /* disable hardware IRQ and firmware flag */ |
518 | ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); | 524 | ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); |
519 | |||
520 | ir_raw_event_set_idle(dev->rdev, true); | 525 | ir_raw_event_set_idle(dev->rdev, true); |
526 | } | ||
527 | |||
528 | /* Disable the device receiver - wrapper to track the state */ | ||
529 | static void ene_rx_disable(struct ene_device *dev) | ||
530 | { | ||
531 | ene_rx_disable_hw(dev); | ||
521 | dev->rx_enabled = false; | 532 | dev->rx_enabled = false; |
522 | } | 533 | } |
523 | 534 | ||
@@ -1022,6 +1033,8 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) | |||
1022 | spin_lock_init(&dev->hw_lock); | 1033 | spin_lock_init(&dev->hw_lock); |
1023 | 1034 | ||
1024 | dev->hw_io = pnp_port_start(pnp_dev, 0); | 1035 | dev->hw_io = pnp_port_start(pnp_dev, 0); |
1036 | dev->irq = pnp_irq(pnp_dev, 0); | ||
1037 | |||
1025 | 1038 | ||
1026 | pnp_set_drvdata(pnp_dev, dev); | 1039 | pnp_set_drvdata(pnp_dev, dev); |
1027 | dev->pnp_dev = pnp_dev; | 1040 | dev->pnp_dev = pnp_dev; |
@@ -1085,7 +1098,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) | |||
1085 | goto exit_unregister_device; | 1098 | goto exit_unregister_device; |
1086 | } | 1099 | } |
1087 | 1100 | ||
1088 | dev->irq = pnp_irq(pnp_dev, 0); | ||
1089 | if (request_irq(dev->irq, ene_isr, | 1101 | if (request_irq(dev->irq, ene_isr, |
1090 | IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) { | 1102 | IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) { |
1091 | goto exit_release_hw_io; | 1103 | goto exit_release_hw_io; |
@@ -1123,9 +1135,8 @@ static void ene_remove(struct pnp_dev *pnp_dev) | |||
1123 | } | 1135 | } |
1124 | 1136 | ||
1125 | /* enable wake on IR (wakes on specific button on original remote) */ | 1137 | /* enable wake on IR (wakes on specific button on original remote) */ |
1126 | static void ene_enable_wake(struct ene_device *dev, int enable) | 1138 | static void ene_enable_wake(struct ene_device *dev, bool enable) |
1127 | { | 1139 | { |
1128 | enable = enable && device_may_wakeup(&dev->pnp_dev->dev); | ||
1129 | dbg("wake on IR %s", enable ? "enabled" : "disabled"); | 1140 | dbg("wake on IR %s", enable ? "enabled" : "disabled"); |
1130 | ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable); | 1141 | ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable); |
1131 | } | 1142 | } |
@@ -1134,9 +1145,12 @@ static void ene_enable_wake(struct ene_device *dev, int enable) | |||
1134 | static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) | 1145 | static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) |
1135 | { | 1146 | { |
1136 | struct ene_device *dev = pnp_get_drvdata(pnp_dev); | 1147 | struct ene_device *dev = pnp_get_drvdata(pnp_dev); |
1137 | ene_enable_wake(dev, true); | 1148 | bool wake = device_may_wakeup(&dev->pnp_dev->dev); |
1149 | |||
1150 | if (!wake && dev->rx_enabled) | ||
1151 | ene_rx_disable_hw(dev); | ||
1138 | 1152 | ||
1139 | /* TODO: add support for wake pattern */ | 1153 | ene_enable_wake(dev, wake); |
1140 | return 0; | 1154 | return 0; |
1141 | } | 1155 | } |
1142 | 1156 | ||
diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h index 6f978e85db8c..a7911e3b9bc0 100644 --- a/drivers/media/rc/ene_ir.h +++ b/drivers/media/rc/ene_ir.h | |||
@@ -185,7 +185,7 @@ | |||
185 | #define __dbg(level, format, ...) \ | 185 | #define __dbg(level, format, ...) \ |
186 | do { \ | 186 | do { \ |
187 | if (debug >= level) \ | 187 | if (debug >= level) \ |
188 | pr_debug(format "\n", ## __VA_ARGS__); \ | 188 | pr_info(format "\n", ## __VA_ARGS__); \ |
189 | } while (0) | 189 | } while (0) |
190 | 190 | ||
191 | #define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__) | 191 | #define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__) |
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index a4ab2e6b3f82..19632b1c2190 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c | |||
@@ -364,8 +364,8 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) | |||
364 | periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); | 364 | periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); |
365 | bytes = DIV_ROUND_UP(periods, 127); | 365 | bytes = DIV_ROUND_UP(periods, 127); |
366 | if (size + bytes > ir->bufsize) { | 366 | if (size + bytes > ir->bufsize) { |
367 | count = i; | 367 | rc = -EINVAL; |
368 | break; | 368 | goto out; |
369 | } | 369 | } |
370 | while (periods > 127) { | 370 | while (periods > 127) { |
371 | ir->packet->payload[size++] = 127 | space; | 371 | ir->packet->payload[size++] = 127 | space; |
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index e4561264e124..ed2c8a1ed8ca 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c | |||
@@ -140,11 +140,20 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
140 | goto out; | 140 | goto out; |
141 | } | 141 | } |
142 | 142 | ||
143 | for (i = 0; i < count; i++) { | ||
144 | if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) { | ||
145 | ret = -EINVAL; | ||
146 | goto out; | ||
147 | } | ||
148 | |||
149 | duration += txbuf[i]; | ||
150 | } | ||
151 | |||
143 | ret = dev->tx_ir(dev, txbuf, count); | 152 | ret = dev->tx_ir(dev, txbuf, count); |
144 | if (ret < 0) | 153 | if (ret < 0) |
145 | goto out; | 154 | goto out; |
146 | 155 | ||
147 | for (i = 0; i < ret; i++) | 156 | for (duration = i = 0; i < ret; i++) |
148 | duration += txbuf[i]; | 157 | duration += txbuf[i]; |
149 | 158 | ||
150 | ret *= sizeof(unsigned int); | 159 | ret *= sizeof(unsigned int); |
@@ -375,6 +384,7 @@ static int ir_lirc_register(struct rc_dev *dev) | |||
375 | drv->code_length = sizeof(struct ir_raw_event) * 8; | 384 | drv->code_length = sizeof(struct ir_raw_event) * 8; |
376 | drv->fops = &lirc_fops; | 385 | drv->fops = &lirc_fops; |
377 | drv->dev = &dev->dev; | 386 | drv->dev = &dev->dev; |
387 | drv->rdev = dev; | ||
378 | drv->owner = THIS_MODULE; | 388 | drv->owner = THIS_MODULE; |
379 | 389 | ||
380 | drv->minor = lirc_register_driver(drv); | 390 | drv->minor = lirc_register_driver(drv); |
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 8dc057b273f2..dc5cbffcd5a2 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/device.h> | 35 | #include <linux/device.h> |
36 | #include <linux/cdev.h> | 36 | #include <linux/cdev.h> |
37 | 37 | ||
38 | #include <media/rc-core.h> | ||
38 | #include <media/lirc.h> | 39 | #include <media/lirc.h> |
39 | #include <media/lirc_dev.h> | 40 | #include <media/lirc_dev.h> |
40 | 41 | ||
@@ -467,6 +468,12 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) | |||
467 | goto error; | 468 | goto error; |
468 | } | 469 | } |
469 | 470 | ||
471 | if (ir->d.rdev) { | ||
472 | retval = rc_open(ir->d.rdev); | ||
473 | if (retval) | ||
474 | goto error; | ||
475 | } | ||
476 | |||
470 | cdev = ir->cdev; | 477 | cdev = ir->cdev; |
471 | if (try_module_get(cdev->owner)) { | 478 | if (try_module_get(cdev->owner)) { |
472 | ir->open++; | 479 | ir->open++; |
@@ -511,6 +518,9 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file) | |||
511 | 518 | ||
512 | WARN_ON(mutex_lock_killable(&lirc_dev_lock)); | 519 | WARN_ON(mutex_lock_killable(&lirc_dev_lock)); |
513 | 520 | ||
521 | if (ir->d.rdev) | ||
522 | rc_close(ir->d.rdev); | ||
523 | |||
514 | ir->open--; | 524 | ir->open--; |
515 | if (ir->attached) { | 525 | if (ir->attached) { |
516 | ir->d.set_use_dec(ir->d.data); | 526 | ir->d.set_use_dec(ir->d.data); |
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 1cf382a0b277..46da365c9c84 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
19 | #include <linux/leds.h> | ||
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <linux/device.h> | 21 | #include <linux/device.h> |
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
@@ -31,6 +32,7 @@ | |||
31 | /* Used to keep track of known keymaps */ | 32 | /* Used to keep track of known keymaps */ |
32 | static LIST_HEAD(rc_map_list); | 33 | static LIST_HEAD(rc_map_list); |
33 | static DEFINE_SPINLOCK(rc_map_lock); | 34 | static DEFINE_SPINLOCK(rc_map_lock); |
35 | static struct led_trigger *led_feedback; | ||
34 | 36 | ||
35 | static struct rc_map_list *seek_rc_map(const char *name) | 37 | static struct rc_map_list *seek_rc_map(const char *name) |
36 | { | 38 | { |
@@ -535,6 +537,7 @@ static void ir_do_keyup(struct rc_dev *dev, bool sync) | |||
535 | 537 | ||
536 | IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode); | 538 | IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode); |
537 | input_report_key(dev->input_dev, dev->last_keycode, 0); | 539 | input_report_key(dev->input_dev, dev->last_keycode, 0); |
540 | led_trigger_event(led_feedback, LED_OFF); | ||
538 | if (sync) | 541 | if (sync) |
539 | input_sync(dev->input_dev); | 542 | input_sync(dev->input_dev); |
540 | dev->keypressed = false; | 543 | dev->keypressed = false; |
@@ -648,6 +651,7 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode, | |||
648 | input_report_key(dev->input_dev, keycode, 1); | 651 | input_report_key(dev->input_dev, keycode, 1); |
649 | } | 652 | } |
650 | 653 | ||
654 | led_trigger_event(led_feedback, LED_FULL); | ||
651 | input_sync(dev->input_dev); | 655 | input_sync(dev->input_dev); |
652 | } | 656 | } |
653 | 657 | ||
@@ -699,19 +703,50 @@ void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle) | |||
699 | } | 703 | } |
700 | EXPORT_SYMBOL_GPL(rc_keydown_notimeout); | 704 | EXPORT_SYMBOL_GPL(rc_keydown_notimeout); |
701 | 705 | ||
706 | int rc_open(struct rc_dev *rdev) | ||
707 | { | ||
708 | int rval = 0; | ||
709 | |||
710 | if (!rdev) | ||
711 | return -EINVAL; | ||
712 | |||
713 | mutex_lock(&rdev->lock); | ||
714 | if (!rdev->users++ && rdev->open != NULL) | ||
715 | rval = rdev->open(rdev); | ||
716 | |||
717 | if (rval) | ||
718 | rdev->users--; | ||
719 | |||
720 | mutex_unlock(&rdev->lock); | ||
721 | |||
722 | return rval; | ||
723 | } | ||
724 | EXPORT_SYMBOL_GPL(rc_open); | ||
725 | |||
702 | static int ir_open(struct input_dev *idev) | 726 | static int ir_open(struct input_dev *idev) |
703 | { | 727 | { |
704 | struct rc_dev *rdev = input_get_drvdata(idev); | 728 | struct rc_dev *rdev = input_get_drvdata(idev); |
705 | 729 | ||
706 | return rdev->open(rdev); | 730 | return rc_open(rdev); |
731 | } | ||
732 | |||
733 | void rc_close(struct rc_dev *rdev) | ||
734 | { | ||
735 | if (rdev) { | ||
736 | mutex_lock(&rdev->lock); | ||
737 | |||
738 | if (!--rdev->users && rdev->close != NULL) | ||
739 | rdev->close(rdev); | ||
740 | |||
741 | mutex_unlock(&rdev->lock); | ||
742 | } | ||
707 | } | 743 | } |
744 | EXPORT_SYMBOL_GPL(rc_close); | ||
708 | 745 | ||
709 | static void ir_close(struct input_dev *idev) | 746 | static void ir_close(struct input_dev *idev) |
710 | { | 747 | { |
711 | struct rc_dev *rdev = input_get_drvdata(idev); | 748 | struct rc_dev *rdev = input_get_drvdata(idev); |
712 | 749 | rc_close(rdev); | |
713 | if (rdev) | ||
714 | rdev->close(rdev); | ||
715 | } | 750 | } |
716 | 751 | ||
717 | /* class for /sys/class/rc */ | 752 | /* class for /sys/class/rc */ |
@@ -1076,7 +1111,14 @@ int rc_register_device(struct rc_dev *dev) | |||
1076 | memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); | 1111 | memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); |
1077 | dev->input_dev->phys = dev->input_phys; | 1112 | dev->input_dev->phys = dev->input_phys; |
1078 | dev->input_dev->name = dev->input_name; | 1113 | dev->input_dev->name = dev->input_name; |
1114 | |||
1115 | /* input_register_device can call ir_open, so unlock mutex here */ | ||
1116 | mutex_unlock(&dev->lock); | ||
1117 | |||
1079 | rc = input_register_device(dev->input_dev); | 1118 | rc = input_register_device(dev->input_dev); |
1119 | |||
1120 | mutex_lock(&dev->lock); | ||
1121 | |||
1080 | if (rc) | 1122 | if (rc) |
1081 | goto out_table; | 1123 | goto out_table; |
1082 | 1124 | ||
@@ -1184,6 +1226,7 @@ static int __init rc_core_init(void) | |||
1184 | return rc; | 1226 | return rc; |
1185 | } | 1227 | } |
1186 | 1228 | ||
1229 | led_trigger_register_simple("rc-feedback", &led_feedback); | ||
1187 | rc_map_register(&empty_map); | 1230 | rc_map_register(&empty_map); |
1188 | 1231 | ||
1189 | return 0; | 1232 | return 0; |
@@ -1192,6 +1235,7 @@ static int __init rc_core_init(void) | |||
1192 | static void __exit rc_core_exit(void) | 1235 | static void __exit rc_core_exit(void) |
1193 | { | 1236 | { |
1194 | class_unregister(&rc_class); | 1237 | class_unregister(&rc_class); |
1238 | led_trigger_unregister_simple(led_feedback); | ||
1195 | rc_map_unregister(&empty_map); | 1239 | rc_map_unregister(&empty_map); |
1196 | } | 1240 | } |
1197 | 1241 | ||
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 12167a6b5472..094484fac94c 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c | |||
@@ -47,6 +47,7 @@ | |||
47 | 47 | ||
48 | #include <asm/unaligned.h> | 48 | #include <asm/unaligned.h> |
49 | #include <linux/device.h> | 49 | #include <linux/device.h> |
50 | #include <linux/leds.h> | ||
50 | #include <linux/module.h> | 51 | #include <linux/module.h> |
51 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
52 | #include <linux/usb.h> | 53 | #include <linux/usb.h> |
@@ -186,6 +187,13 @@ struct redrat3_dev { | |||
186 | struct rc_dev *rc; | 187 | struct rc_dev *rc; |
187 | struct device *dev; | 188 | struct device *dev; |
188 | 189 | ||
190 | /* led control */ | ||
191 | struct led_classdev led; | ||
192 | atomic_t flash; | ||
193 | struct usb_ctrlrequest flash_control; | ||
194 | struct urb *flash_urb; | ||
195 | u8 flash_in_buf; | ||
196 | |||
189 | /* save off the usb device pointer */ | 197 | /* save off the usb device pointer */ |
190 | struct usb_device *udev; | 198 | struct usb_device *udev; |
191 | 199 | ||
@@ -206,8 +214,6 @@ struct redrat3_dev { | |||
206 | struct timer_list rx_timeout; | 214 | struct timer_list rx_timeout; |
207 | u32 hw_timeout; | 215 | u32 hw_timeout; |
208 | 216 | ||
209 | /* is the detector enabled*/ | ||
210 | bool det_enabled; | ||
211 | /* Is the device currently transmitting?*/ | 217 | /* Is the device currently transmitting?*/ |
212 | bool transmitting; | 218 | bool transmitting; |
213 | 219 | ||
@@ -472,40 +478,19 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3) | |||
472 | return -EIO; | 478 | return -EIO; |
473 | } | 479 | } |
474 | 480 | ||
475 | rr3->det_enabled = true; | ||
476 | redrat3_issue_async(rr3); | 481 | redrat3_issue_async(rr3); |
477 | 482 | ||
478 | return 0; | 483 | return 0; |
479 | } | 484 | } |
480 | 485 | ||
481 | /* Disables the rr3 long range detector */ | ||
482 | static void redrat3_disable_detector(struct redrat3_dev *rr3) | ||
483 | { | ||
484 | struct device *dev = rr3->dev; | ||
485 | u8 ret; | ||
486 | |||
487 | rr3_ftr(dev, "Entering %s\n", __func__); | ||
488 | |||
489 | ret = redrat3_send_cmd(RR3_RC_DET_DISABLE, rr3); | ||
490 | if (ret != 0) | ||
491 | dev_err(dev, "%s: failure!\n", __func__); | ||
492 | |||
493 | ret = redrat3_send_cmd(RR3_RC_DET_STATUS, rr3); | ||
494 | if (ret != 0) | ||
495 | dev_warn(dev, "%s: detector status: %d, should be 0\n", | ||
496 | __func__, ret); | ||
497 | |||
498 | rr3->det_enabled = false; | ||
499 | } | ||
500 | |||
501 | static inline void redrat3_delete(struct redrat3_dev *rr3, | 486 | static inline void redrat3_delete(struct redrat3_dev *rr3, |
502 | struct usb_device *udev) | 487 | struct usb_device *udev) |
503 | { | 488 | { |
504 | rr3_ftr(rr3->dev, "%s cleaning up\n", __func__); | 489 | rr3_ftr(rr3->dev, "%s cleaning up\n", __func__); |
505 | usb_kill_urb(rr3->read_urb); | 490 | usb_kill_urb(rr3->read_urb); |
506 | 491 | usb_kill_urb(rr3->flash_urb); | |
507 | usb_free_urb(rr3->read_urb); | 492 | usb_free_urb(rr3->read_urb); |
508 | 493 | usb_free_urb(rr3->flash_urb); | |
509 | usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize), | 494 | usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize), |
510 | rr3->bulk_in_buf, rr3->dma_in); | 495 | rr3->bulk_in_buf, rr3->dma_in); |
511 | 496 | ||
@@ -686,7 +671,8 @@ static int redrat3_get_ir_data(struct redrat3_dev *rr3, unsigned len) | |||
686 | goto out; | 671 | goto out; |
687 | } | 672 | } |
688 | 673 | ||
689 | if (rr3->bytes_read < be16_to_cpu(rr3->irdata.header.length)) | 674 | if (rr3->bytes_read < be16_to_cpu(rr3->irdata.header.length) + |
675 | sizeof(struct redrat3_header)) | ||
690 | /* we're still accumulating data */ | 676 | /* we're still accumulating data */ |
691 | return 0; | 677 | return 0; |
692 | 678 | ||
@@ -785,10 +771,10 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, | |||
785 | return -EAGAIN; | 771 | return -EAGAIN; |
786 | } | 772 | } |
787 | 773 | ||
788 | count = min_t(unsigned, count, RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN); | 774 | if (count > RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN) |
775 | return -EINVAL; | ||
789 | 776 | ||
790 | /* rr3 will disable rc detector on transmit */ | 777 | /* rr3 will disable rc detector on transmit */ |
791 | rr3->det_enabled = false; | ||
792 | rr3->transmitting = true; | 778 | rr3->transmitting = true; |
793 | 779 | ||
794 | sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); | 780 | sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); |
@@ -825,8 +811,8 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, | |||
825 | &irdata->lens[curlencheck]); | 811 | &irdata->lens[curlencheck]); |
826 | curlencheck++; | 812 | curlencheck++; |
827 | } else { | 813 | } else { |
828 | count = i - 1; | 814 | ret = -EINVAL; |
829 | break; | 815 | goto out; |
830 | } | 816 | } |
831 | } | 817 | } |
832 | irdata->sigdata[i] = lencheck; | 818 | irdata->sigdata[i] = lencheck; |
@@ -868,11 +854,48 @@ out: | |||
868 | 854 | ||
869 | rr3->transmitting = false; | 855 | rr3->transmitting = false; |
870 | /* rr3 re-enables rc detector because it was enabled before */ | 856 | /* rr3 re-enables rc detector because it was enabled before */ |
871 | rr3->det_enabled = true; | ||
872 | 857 | ||
873 | return ret; | 858 | return ret; |
874 | } | 859 | } |
875 | 860 | ||
861 | static void redrat3_brightness_set(struct led_classdev *led_dev, enum | ||
862 | led_brightness brightness) | ||
863 | { | ||
864 | struct redrat3_dev *rr3 = container_of(led_dev, struct redrat3_dev, | ||
865 | led); | ||
866 | |||
867 | if (brightness != LED_OFF && atomic_cmpxchg(&rr3->flash, 0, 1) == 0) { | ||
868 | int ret = usb_submit_urb(rr3->flash_urb, GFP_ATOMIC); | ||
869 | if (ret != 0) { | ||
870 | dev_dbg(rr3->dev, "%s: unexpected ret of %d\n", | ||
871 | __func__, ret); | ||
872 | atomic_set(&rr3->flash, 0); | ||
873 | } | ||
874 | } | ||
875 | } | ||
876 | |||
877 | static void redrat3_led_complete(struct urb *urb) | ||
878 | { | ||
879 | struct redrat3_dev *rr3 = urb->context; | ||
880 | |||
881 | switch (urb->status) { | ||
882 | case 0: | ||
883 | break; | ||
884 | case -ECONNRESET: | ||
885 | case -ENOENT: | ||
886 | case -ESHUTDOWN: | ||
887 | usb_unlink_urb(urb); | ||
888 | return; | ||
889 | case -EPIPE: | ||
890 | default: | ||
891 | dev_dbg(rr3->dev, "Error: urb status = %d\n", urb->status); | ||
892 | break; | ||
893 | } | ||
894 | |||
895 | rr3->led.brightness = LED_OFF; | ||
896 | atomic_dec(&rr3->flash); | ||
897 | } | ||
898 | |||
876 | static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) | 899 | static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) |
877 | { | 900 | { |
878 | struct device *dev = rr3->dev; | 901 | struct device *dev = rr3->dev; |
@@ -1016,10 +1039,35 @@ static int redrat3_dev_probe(struct usb_interface *intf, | |||
1016 | /* default.. will get overridden by any sends with a freq defined */ | 1039 | /* default.. will get overridden by any sends with a freq defined */ |
1017 | rr3->carrier = 38000; | 1040 | rr3->carrier = 38000; |
1018 | 1041 | ||
1042 | /* led control */ | ||
1043 | rr3->led.name = "redrat3:red:feedback"; | ||
1044 | rr3->led.default_trigger = "rc-feedback"; | ||
1045 | rr3->led.brightness_set = redrat3_brightness_set; | ||
1046 | retval = led_classdev_register(&intf->dev, &rr3->led); | ||
1047 | if (retval) | ||
1048 | goto error; | ||
1049 | |||
1050 | atomic_set(&rr3->flash, 0); | ||
1051 | rr3->flash_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1052 | if (!rr3->flash_urb) { | ||
1053 | retval = -ENOMEM; | ||
1054 | goto led_free_error; | ||
1055 | } | ||
1056 | |||
1057 | /* setup packet is 'c0 b9 0000 0000 0001' */ | ||
1058 | rr3->flash_control.bRequestType = 0xc0; | ||
1059 | rr3->flash_control.bRequest = RR3_BLINK_LED; | ||
1060 | rr3->flash_control.wLength = cpu_to_le16(1); | ||
1061 | |||
1062 | usb_fill_control_urb(rr3->flash_urb, udev, usb_rcvctrlpipe(udev, 0), | ||
1063 | (unsigned char *)&rr3->flash_control, | ||
1064 | &rr3->flash_in_buf, sizeof(rr3->flash_in_buf), | ||
1065 | redrat3_led_complete, rr3); | ||
1066 | |||
1019 | rr3->rc = redrat3_init_rc_dev(rr3); | 1067 | rr3->rc = redrat3_init_rc_dev(rr3); |
1020 | if (!rr3->rc) { | 1068 | if (!rr3->rc) { |
1021 | retval = -ENOMEM; | 1069 | retval = -ENOMEM; |
1022 | goto error; | 1070 | goto led_free_error; |
1023 | } | 1071 | } |
1024 | setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); | 1072 | setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); |
1025 | 1073 | ||
@@ -1029,6 +1077,8 @@ static int redrat3_dev_probe(struct usb_interface *intf, | |||
1029 | rr3_ftr(dev, "Exiting %s\n", __func__); | 1077 | rr3_ftr(dev, "Exiting %s\n", __func__); |
1030 | return 0; | 1078 | return 0; |
1031 | 1079 | ||
1080 | led_free_error: | ||
1081 | led_classdev_unregister(&rr3->led); | ||
1032 | error: | 1082 | error: |
1033 | redrat3_delete(rr3, rr3->udev); | 1083 | redrat3_delete(rr3, rr3->udev); |
1034 | 1084 | ||
@@ -1048,10 +1098,9 @@ static void redrat3_dev_disconnect(struct usb_interface *intf) | |||
1048 | if (!rr3) | 1098 | if (!rr3) |
1049 | return; | 1099 | return; |
1050 | 1100 | ||
1051 | redrat3_disable_detector(rr3); | ||
1052 | |||
1053 | usb_set_intfdata(intf, NULL); | 1101 | usb_set_intfdata(intf, NULL); |
1054 | rc_unregister_device(rr3->rc); | 1102 | rc_unregister_device(rr3->rc); |
1103 | led_classdev_unregister(&rr3->led); | ||
1055 | del_timer_sync(&rr3->rx_timeout); | 1104 | del_timer_sync(&rr3->rx_timeout); |
1056 | redrat3_delete(rr3, udev); | 1105 | redrat3_delete(rr3, udev); |
1057 | 1106 | ||
@@ -1062,7 +1111,9 @@ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message) | |||
1062 | { | 1111 | { |
1063 | struct redrat3_dev *rr3 = usb_get_intfdata(intf); | 1112 | struct redrat3_dev *rr3 = usb_get_intfdata(intf); |
1064 | rr3_ftr(rr3->dev, "suspend\n"); | 1113 | rr3_ftr(rr3->dev, "suspend\n"); |
1114 | led_classdev_suspend(&rr3->led); | ||
1065 | usb_kill_urb(rr3->read_urb); | 1115 | usb_kill_urb(rr3->read_urb); |
1116 | usb_kill_urb(rr3->flash_urb); | ||
1066 | return 0; | 1117 | return 0; |
1067 | } | 1118 | } |
1068 | 1119 | ||
@@ -1072,6 +1123,7 @@ static int redrat3_dev_resume(struct usb_interface *intf) | |||
1072 | rr3_ftr(rr3->dev, "resume\n"); | 1123 | rr3_ftr(rr3->dev, "resume\n"); |
1073 | if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) | 1124 | if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) |
1074 | return -EIO; | 1125 | return -EIO; |
1126 | led_classdev_resume(&rr3->led); | ||
1075 | return 0; | 1127 | return 0; |
1076 | } | 1128 | } |
1077 | 1129 | ||
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c index 891762d167ed..d8de2056a4f6 100644 --- a/drivers/media/rc/ttusbir.c +++ b/drivers/media/rc/ttusbir.c | |||
@@ -302,6 +302,7 @@ static int ttusbir_probe(struct usb_interface *intf, | |||
302 | ttusbir_bulk_complete, tt); | 302 | ttusbir_bulk_complete, tt); |
303 | 303 | ||
304 | tt->led.name = "ttusbir:green:power"; | 304 | tt->led.name = "ttusbir:green:power"; |
305 | tt->led.default_trigger = "rc-feedback"; | ||
305 | tt->led.brightness_set = ttusbir_brightness_set; | 306 | tt->led.brightness_set = ttusbir_brightness_set; |
306 | tt->led.brightness_get = ttusbir_brightness_get; | 307 | tt->led.brightness_get = ttusbir_brightness_get; |
307 | tt->is_led_on = tt->led_on = true; | 308 | tt->is_led_on = tt->led_on = true; |
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 87af2d3ba601..98bd4960c75e 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c | |||
@@ -213,13 +213,11 @@ struct wbcir_data { | |||
213 | 213 | ||
214 | /* RX state */ | 214 | /* RX state */ |
215 | enum wbcir_rxstate rxstate; | 215 | enum wbcir_rxstate rxstate; |
216 | struct led_trigger *rxtrigger; | ||
217 | int carrier_report_enabled; | 216 | int carrier_report_enabled; |
218 | u32 pulse_duration; | 217 | u32 pulse_duration; |
219 | 218 | ||
220 | /* TX state */ | 219 | /* TX state */ |
221 | enum wbcir_txstate txstate; | 220 | enum wbcir_txstate txstate; |
222 | struct led_trigger *txtrigger; | ||
223 | u32 txlen; | 221 | u32 txlen; |
224 | u32 txoff; | 222 | u32 txoff; |
225 | u32 *txbuf; | 223 | u32 *txbuf; |
@@ -366,14 +364,11 @@ wbcir_idle_rx(struct rc_dev *dev, bool idle) | |||
366 | { | 364 | { |
367 | struct wbcir_data *data = dev->priv; | 365 | struct wbcir_data *data = dev->priv; |
368 | 366 | ||
369 | if (!idle && data->rxstate == WBCIR_RXSTATE_INACTIVE) { | 367 | if (!idle && data->rxstate == WBCIR_RXSTATE_INACTIVE) |
370 | data->rxstate = WBCIR_RXSTATE_ACTIVE; | 368 | data->rxstate = WBCIR_RXSTATE_ACTIVE; |
371 | led_trigger_event(data->rxtrigger, LED_FULL); | ||
372 | } | ||
373 | 369 | ||
374 | if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) { | 370 | if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) { |
375 | data->rxstate = WBCIR_RXSTATE_INACTIVE; | 371 | data->rxstate = WBCIR_RXSTATE_INACTIVE; |
376 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
377 | 372 | ||
378 | if (data->carrier_report_enabled) | 373 | if (data->carrier_report_enabled) |
379 | wbcir_carrier_report(data); | 374 | wbcir_carrier_report(data); |
@@ -425,7 +420,6 @@ wbcir_irq_tx(struct wbcir_data *data) | |||
425 | case WBCIR_TXSTATE_INACTIVE: | 420 | case WBCIR_TXSTATE_INACTIVE: |
426 | /* TX FIFO empty */ | 421 | /* TX FIFO empty */ |
427 | space = 16; | 422 | space = 16; |
428 | led_trigger_event(data->txtrigger, LED_FULL); | ||
429 | break; | 423 | break; |
430 | case WBCIR_TXSTATE_ACTIVE: | 424 | case WBCIR_TXSTATE_ACTIVE: |
431 | /* TX FIFO low (3 bytes or less) */ | 425 | /* TX FIFO low (3 bytes or less) */ |
@@ -464,7 +458,6 @@ wbcir_irq_tx(struct wbcir_data *data) | |||
464 | /* Clear TX underrun bit */ | 458 | /* Clear TX underrun bit */ |
465 | outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR); | 459 | outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR); |
466 | wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); | 460 | wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); |
467 | led_trigger_event(data->txtrigger, LED_OFF); | ||
468 | kfree(data->txbuf); | 461 | kfree(data->txbuf); |
469 | data->txbuf = NULL; | 462 | data->txbuf = NULL; |
470 | data->txstate = WBCIR_TXSTATE_INACTIVE; | 463 | data->txstate = WBCIR_TXSTATE_INACTIVE; |
@@ -878,15 +871,13 @@ finish: | |||
878 | */ | 871 | */ |
879 | wbcir_set_irqmask(data, WBCIR_IRQ_NONE); | 872 | wbcir_set_irqmask(data, WBCIR_IRQ_NONE); |
880 | disable_irq(data->irq); | 873 | disable_irq(data->irq); |
881 | |||
882 | /* Disable LED */ | ||
883 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
884 | led_trigger_event(data->txtrigger, LED_OFF); | ||
885 | } | 874 | } |
886 | 875 | ||
887 | static int | 876 | static int |
888 | wbcir_suspend(struct pnp_dev *device, pm_message_t state) | 877 | wbcir_suspend(struct pnp_dev *device, pm_message_t state) |
889 | { | 878 | { |
879 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
880 | led_classdev_suspend(&data->led); | ||
890 | wbcir_shutdown(device); | 881 | wbcir_shutdown(device); |
891 | return 0; | 882 | return 0; |
892 | } | 883 | } |
@@ -1015,6 +1006,7 @@ wbcir_resume(struct pnp_dev *device) | |||
1015 | 1006 | ||
1016 | wbcir_init_hw(data); | 1007 | wbcir_init_hw(data); |
1017 | enable_irq(data->irq); | 1008 | enable_irq(data->irq); |
1009 | led_classdev_resume(&data->led); | ||
1018 | 1010 | ||
1019 | return 0; | 1011 | return 0; |
1020 | } | 1012 | } |
@@ -1058,25 +1050,13 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
1058 | "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", | 1050 | "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", |
1059 | data->wbase, data->ebase, data->sbase, data->irq); | 1051 | data->wbase, data->ebase, data->sbase, data->irq); |
1060 | 1052 | ||
1061 | led_trigger_register_simple("cir-tx", &data->txtrigger); | ||
1062 | if (!data->txtrigger) { | ||
1063 | err = -ENOMEM; | ||
1064 | goto exit_free_data; | ||
1065 | } | ||
1066 | |||
1067 | led_trigger_register_simple("cir-rx", &data->rxtrigger); | ||
1068 | if (!data->rxtrigger) { | ||
1069 | err = -ENOMEM; | ||
1070 | goto exit_unregister_txtrigger; | ||
1071 | } | ||
1072 | |||
1073 | data->led.name = "cir::activity"; | 1053 | data->led.name = "cir::activity"; |
1074 | data->led.default_trigger = "cir-rx"; | 1054 | data->led.default_trigger = "rc-feedback"; |
1075 | data->led.brightness_set = wbcir_led_brightness_set; | 1055 | data->led.brightness_set = wbcir_led_brightness_set; |
1076 | data->led.brightness_get = wbcir_led_brightness_get; | 1056 | data->led.brightness_get = wbcir_led_brightness_get; |
1077 | err = led_classdev_register(&device->dev, &data->led); | 1057 | err = led_classdev_register(&device->dev, &data->led); |
1078 | if (err) | 1058 | if (err) |
1079 | goto exit_unregister_rxtrigger; | 1059 | goto exit_free_data; |
1080 | 1060 | ||
1081 | data->dev = rc_allocate_device(); | 1061 | data->dev = rc_allocate_device(); |
1082 | if (!data->dev) { | 1062 | if (!data->dev) { |
@@ -1156,10 +1136,6 @@ exit_free_rc: | |||
1156 | rc_free_device(data->dev); | 1136 | rc_free_device(data->dev); |
1157 | exit_unregister_led: | 1137 | exit_unregister_led: |
1158 | led_classdev_unregister(&data->led); | 1138 | led_classdev_unregister(&data->led); |
1159 | exit_unregister_rxtrigger: | ||
1160 | led_trigger_unregister_simple(data->rxtrigger); | ||
1161 | exit_unregister_txtrigger: | ||
1162 | led_trigger_unregister_simple(data->txtrigger); | ||
1163 | exit_free_data: | 1139 | exit_free_data: |
1164 | kfree(data); | 1140 | kfree(data); |
1165 | pnp_set_drvdata(device, NULL); | 1141 | pnp_set_drvdata(device, NULL); |
@@ -1187,8 +1163,6 @@ wbcir_remove(struct pnp_dev *device) | |||
1187 | 1163 | ||
1188 | rc_unregister_device(data->dev); | 1164 | rc_unregister_device(data->dev); |
1189 | 1165 | ||
1190 | led_trigger_unregister_simple(data->rxtrigger); | ||
1191 | led_trigger_unregister_simple(data->txtrigger); | ||
1192 | led_classdev_unregister(&data->led); | 1166 | led_classdev_unregister(&data->led); |
1193 | 1167 | ||
1194 | /* This is ok since &data->led isn't actually used */ | 1168 | /* This is ok since &data->led isn't actually used */ |
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c index 1b33ed368abe..ad9309da4a91 100644 --- a/drivers/media/tuners/e4000.c +++ b/drivers/media/tuners/e4000.c | |||
@@ -41,8 +41,9 @@ static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) | |||
41 | if (ret == 1) { | 41 | if (ret == 1) { |
42 | ret = 0; | 42 | ret = 0; |
43 | } else { | 43 | } else { |
44 | dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ | 44 | dev_warn(&priv->i2c->dev, |
45 | "len=%d\n", KBUILD_MODNAME, ret, reg, len); | 45 | "%s: i2c wr failed=%d reg=%02x len=%d\n", |
46 | KBUILD_MODNAME, ret, reg, len); | ||
46 | ret = -EREMOTEIO; | 47 | ret = -EREMOTEIO; |
47 | } | 48 | } |
48 | return ret; | 49 | return ret; |
@@ -72,8 +73,9 @@ static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) | |||
72 | memcpy(val, buf, len); | 73 | memcpy(val, buf, len); |
73 | ret = 0; | 74 | ret = 0; |
74 | } else { | 75 | } else { |
75 | dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ | 76 | dev_warn(&priv->i2c->dev, |
76 | "len=%d\n", KBUILD_MODNAME, ret, reg, len); | 77 | "%s: i2c rd failed=%d reg=%02x len=%d\n", |
78 | KBUILD_MODNAME, ret, reg, len); | ||
77 | ret = -EREMOTEIO; | 79 | ret = -EREMOTEIO; |
78 | } | 80 | } |
79 | 81 | ||
@@ -140,14 +142,12 @@ static int e4000_init(struct dvb_frontend *fe) | |||
140 | if (ret < 0) | 142 | if (ret < 0) |
141 | goto err; | 143 | goto err; |
142 | 144 | ||
143 | /* | ||
144 | * TODO: Implement DC offset control correctly. | ||
145 | * DC offsets has quite much effect for received signal quality in case | ||
146 | * of direct conversion tuners (Zero-IF). Surely we will now lose few | ||
147 | * decimals or even decibels from SNR... | ||
148 | */ | ||
149 | /* DC offset control */ | 145 | /* DC offset control */ |
150 | ret = e4000_wr_reg(priv, 0x2d, 0x0c); | 146 | ret = e4000_wr_reg(priv, 0x2d, 0x1f); |
147 | if (ret < 0) | ||
148 | goto err; | ||
149 | |||
150 | ret = e4000_wr_regs(priv, 0x70, "\x01\x01", 2); | ||
151 | if (ret < 0) | 151 | if (ret < 0) |
152 | goto err; | 152 | goto err; |
153 | 153 | ||
@@ -203,12 +203,13 @@ static int e4000_set_params(struct dvb_frontend *fe) | |||
203 | struct e4000_priv *priv = fe->tuner_priv; | 203 | struct e4000_priv *priv = fe->tuner_priv; |
204 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 204 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
205 | int ret, i, sigma_delta; | 205 | int ret, i, sigma_delta; |
206 | unsigned int f_VCO; | 206 | unsigned int f_vco; |
207 | u8 buf[5]; | 207 | u8 buf[5], i_data[4], q_data[4]; |
208 | 208 | ||
209 | dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \ | 209 | dev_dbg(&priv->i2c->dev, |
210 | "bandwidth_hz=%d\n", __func__, | 210 | "%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", |
211 | c->delivery_system, c->frequency, c->bandwidth_hz); | 211 | __func__, c->delivery_system, c->frequency, |
212 | c->bandwidth_hz); | ||
212 | 213 | ||
213 | if (fe->ops.i2c_gate_ctrl) | 214 | if (fe->ops.i2c_gate_ctrl) |
214 | fe->ops.i2c_gate_ctrl(fe, 1); | 215 | fe->ops.i2c_gate_ctrl(fe, 1); |
@@ -228,19 +229,19 @@ static int e4000_set_params(struct dvb_frontend *fe) | |||
228 | goto err; | 229 | goto err; |
229 | 230 | ||
230 | /* | 231 | /* |
231 | * Note: Currently f_VCO overflows when c->frequency is 1 073 741 824 Hz | 232 | * Note: Currently f_vco overflows when c->frequency is 1 073 741 824 Hz |
232 | * or more. | 233 | * or more. |
233 | */ | 234 | */ |
234 | f_VCO = c->frequency * e4000_pll_lut[i].mul; | 235 | f_vco = c->frequency * e4000_pll_lut[i].mul; |
235 | sigma_delta = 0x10000UL * (f_VCO % priv->cfg->clock) / priv->cfg->clock; | 236 | sigma_delta = 0x10000UL * (f_vco % priv->cfg->clock) / priv->cfg->clock; |
236 | buf[0] = f_VCO / priv->cfg->clock; | 237 | buf[0] = f_vco / priv->cfg->clock; |
237 | buf[1] = (sigma_delta >> 0) & 0xff; | 238 | buf[1] = (sigma_delta >> 0) & 0xff; |
238 | buf[2] = (sigma_delta >> 8) & 0xff; | 239 | buf[2] = (sigma_delta >> 8) & 0xff; |
239 | buf[3] = 0x00; | 240 | buf[3] = 0x00; |
240 | buf[4] = e4000_pll_lut[i].div; | 241 | buf[4] = e4000_pll_lut[i].div; |
241 | 242 | ||
242 | dev_dbg(&priv->i2c->dev, "%s: f_VCO=%u pll div=%d sigma_delta=%04x\n", | 243 | dev_dbg(&priv->i2c->dev, "%s: f_vco=%u pll div=%d sigma_delta=%04x\n", |
243 | __func__, f_VCO, buf[0], sigma_delta); | 244 | __func__, f_vco, buf[0], sigma_delta); |
244 | 245 | ||
245 | ret = e4000_wr_regs(priv, 0x09, buf, 5); | 246 | ret = e4000_wr_regs(priv, 0x09, buf, 5); |
246 | if (ret < 0) | 247 | if (ret < 0) |
@@ -292,6 +293,43 @@ static int e4000_set_params(struct dvb_frontend *fe) | |||
292 | if (ret < 0) | 293 | if (ret < 0) |
293 | goto err; | 294 | goto err; |
294 | 295 | ||
296 | /* DC offset */ | ||
297 | for (i = 0; i < 4; i++) { | ||
298 | if (i == 0) | ||
299 | ret = e4000_wr_regs(priv, 0x15, "\x00\x7e\x24", 3); | ||
300 | else if (i == 1) | ||
301 | ret = e4000_wr_regs(priv, 0x15, "\x00\x7f", 2); | ||
302 | else if (i == 2) | ||
303 | ret = e4000_wr_regs(priv, 0x15, "\x01", 1); | ||
304 | else | ||
305 | ret = e4000_wr_regs(priv, 0x16, "\x7e", 1); | ||
306 | |||
307 | if (ret < 0) | ||
308 | goto err; | ||
309 | |||
310 | ret = e4000_wr_reg(priv, 0x29, 0x01); | ||
311 | if (ret < 0) | ||
312 | goto err; | ||
313 | |||
314 | ret = e4000_rd_regs(priv, 0x2a, buf, 3); | ||
315 | if (ret < 0) | ||
316 | goto err; | ||
317 | |||
318 | i_data[i] = (((buf[2] >> 0) & 0x3) << 6) | (buf[0] & 0x3f); | ||
319 | q_data[i] = (((buf[2] >> 4) & 0x3) << 6) | (buf[1] & 0x3f); | ||
320 | } | ||
321 | |||
322 | swap(q_data[2], q_data[3]); | ||
323 | swap(i_data[2], i_data[3]); | ||
324 | |||
325 | ret = e4000_wr_regs(priv, 0x50, q_data, 4); | ||
326 | if (ret < 0) | ||
327 | goto err; | ||
328 | |||
329 | ret = e4000_wr_regs(priv, 0x60, i_data, 4); | ||
330 | if (ret < 0) | ||
331 | goto err; | ||
332 | |||
295 | /* gain control auto */ | 333 | /* gain control auto */ |
296 | ret = e4000_wr_reg(priv, 0x1a, 0x17); | 334 | ret = e4000_wr_reg(priv, 0x1a, 0x17); |
297 | if (ret < 0) | 335 | if (ret < 0) |
diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h index 3783a0bdf855..25ee7c07abff 100644 --- a/drivers/media/tuners/e4000.h +++ b/drivers/media/tuners/e4000.h | |||
@@ -44,7 +44,7 @@ extern struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, | |||
44 | static inline struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, | 44 | static inline struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, |
45 | struct i2c_adapter *i2c, const struct e4000_config *cfg) | 45 | struct i2c_adapter *i2c, const struct e4000_config *cfg) |
46 | { | 46 | { |
47 | pr_warn("%s: driver disabled by Kconfig\n", __func__); | 47 | dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); |
48 | return NULL; | 48 | return NULL; |
49 | } | 49 | } |
50 | #endif | 50 | #endif |
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 27948e1798eb..a384f80f595e 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c | |||
@@ -443,6 +443,44 @@ struct cx231xx_board cx231xx_boards[] = { | |||
443 | .gpio = NULL, | 443 | .gpio = NULL, |
444 | } }, | 444 | } }, |
445 | }, | 445 | }, |
446 | [CX231XX_BOARD_KWORLD_UB445_USB_HYBRID] = { | ||
447 | .name = "Kworld UB445 USB Hybrid", | ||
448 | .tuner_type = TUNER_NXP_TDA18271, | ||
449 | .tuner_addr = 0x60, | ||
450 | .decoder = CX231XX_AVDECODER, | ||
451 | .output_mode = OUT_MODE_VIP11, | ||
452 | .demod_xfer_mode = 0, | ||
453 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
454 | .agc_analog_digital_select_gpio = 0x11, /* According with PV cxPolaris.inf file */ | ||
455 | .tuner_sif_gpio = -1, | ||
456 | .tuner_scl_gpio = -1, | ||
457 | .tuner_sda_gpio = -1, | ||
458 | .gpio_pin_status_mask = 0x4001000, | ||
459 | .tuner_i2c_master = 2, | ||
460 | .demod_i2c_master = 1, | ||
461 | .ir_i2c_master = 2, | ||
462 | .has_dvb = 1, | ||
463 | .demod_addr = 0x10, | ||
464 | .norm = V4L2_STD_NTSC_M, | ||
465 | .input = {{ | ||
466 | .type = CX231XX_VMUX_TELEVISION, | ||
467 | .vmux = CX231XX_VIN_3_1, | ||
468 | .amux = CX231XX_AMUX_VIDEO, | ||
469 | .gpio = NULL, | ||
470 | }, { | ||
471 | .type = CX231XX_VMUX_COMPOSITE1, | ||
472 | .vmux = CX231XX_VIN_2_1, | ||
473 | .amux = CX231XX_AMUX_LINE_IN, | ||
474 | .gpio = NULL, | ||
475 | }, { | ||
476 | .type = CX231XX_VMUX_SVIDEO, | ||
477 | .vmux = CX231XX_VIN_1_1 | | ||
478 | (CX231XX_VIN_1_2 << 8) | | ||
479 | CX25840_SVIDEO_ON, | ||
480 | .amux = CX231XX_AMUX_LINE_IN, | ||
481 | .gpio = NULL, | ||
482 | } }, | ||
483 | }, | ||
446 | [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { | 484 | [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { |
447 | .name = "Pixelview PlayTV USB Hybrid", | 485 | .name = "Pixelview PlayTV USB Hybrid", |
448 | .tuner_type = TUNER_NXP_TDA18271, | 486 | .tuner_type = TUNER_NXP_TDA18271, |
@@ -703,6 +741,8 @@ struct usb_device_id cx231xx_id_table[] = { | |||
703 | .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, | 741 | .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, |
704 | {USB_DEVICE(0x1b80, 0xe424), | 742 | {USB_DEVICE(0x1b80, 0xe424), |
705 | .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID}, | 743 | .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID}, |
744 | {USB_DEVICE(0x1b80, 0xe421), | ||
745 | .driver_info = CX231XX_BOARD_KWORLD_UB445_USB_HYBRID}, | ||
706 | {USB_DEVICE(0x1f4d, 0x0237), | 746 | {USB_DEVICE(0x1f4d, 0x0237), |
707 | .driver_info = CX231XX_BOARD_ICONBIT_U100}, | 747 | .driver_info = CX231XX_BOARD_ICONBIT_U100}, |
708 | {USB_DEVICE(0x0fd9, 0x0037), | 748 | {USB_DEVICE(0x0fd9, 0x0037), |
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 14e26106fd72..4504bc6a700b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c | |||
@@ -657,6 +657,7 @@ static int dvb_init(struct cx231xx *dev) | |||
657 | } | 657 | } |
658 | break; | 658 | break; |
659 | case CX231XX_BOARD_CNXT_RDU_253S: | 659 | case CX231XX_BOARD_CNXT_RDU_253S: |
660 | case CX231XX_BOARD_KWORLD_UB445_USB_HYBRID: | ||
660 | 661 | ||
661 | dev->dvb->frontend = dvb_attach(s5h1411_attach, | 662 | dev->dvb->frontend = dvb_attach(s5h1411_attach, |
662 | &tda18271_s5h1411_config, | 663 | &tda18271_s5h1411_config, |
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index e812119ea7a8..babca7fb85e2 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h | |||
@@ -72,6 +72,7 @@ | |||
72 | #define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15 | 72 | #define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15 |
73 | #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16 | 73 | #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16 |
74 | #define CX231XX_BOARD_OTG102 17 | 74 | #define CX231XX_BOARD_OTG102 17 |
75 | #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18 | ||
75 | 76 | ||
76 | /* Limits minimum and default number of buffers */ | 77 | /* Limits minimum and default number of buffers */ |
77 | #define CX231XX_MIN_BUF 4 | 78 | #define CX231XX_MIN_BUF 4 |
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig index a3c8ecf22078..2059d0c86ad3 100644 --- a/drivers/media/usb/dvb-usb-v2/Kconfig +++ b/drivers/media/usb/dvb-usb-v2/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config DVB_USB_V2 | 1 | config DVB_USB_V2 |
2 | tristate "Support for various USB DVB devices v2" | 2 | tristate "Support for various USB DVB devices v2" |
3 | depends on DVB_CORE && USB && I2C | 3 | depends on DVB_CORE && USB && I2C && (RC_CORE || RC_CORE=n) |
4 | help | 4 | help |
5 | By enabling this you will be able to choose the various supported | 5 | By enabling this you will be able to choose the various supported |
6 | USB1.1 and USB2.0 DVB devices. | 6 | USB1.1 and USB2.0 DVB devices. |
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 399916bd588f..124b4baa7e97 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h | |||
@@ -352,9 +352,7 @@ struct dvb_usb_adapter { | |||
352 | * @rc_map: name of rc codes table | 352 | * @rc_map: name of rc codes table |
353 | * @rc_polling_active: set when RC polling is active | 353 | * @rc_polling_active: set when RC polling is active |
354 | * @udev: pointer to the device's struct usb_device | 354 | * @udev: pointer to the device's struct usb_device |
355 | * @intf: pointer to the device's usb interface | ||
356 | * @rc: remote controller configuration | 355 | * @rc: remote controller configuration |
357 | * @probe_work: work to defer .probe() | ||
358 | * @powered: indicated whether the device is power or not | 356 | * @powered: indicated whether the device is power or not |
359 | * @usb_mutex: mutex for usb control messages | 357 | * @usb_mutex: mutex for usb control messages |
360 | * @i2c_mutex: mutex for i2c-transfers | 358 | * @i2c_mutex: mutex for i2c-transfers |
@@ -370,10 +368,7 @@ struct dvb_usb_device { | |||
370 | const char *rc_map; | 368 | const char *rc_map; |
371 | bool rc_polling_active; | 369 | bool rc_polling_active; |
372 | struct usb_device *udev; | 370 | struct usb_device *udev; |
373 | struct usb_interface *intf; | ||
374 | struct dvb_usb_rc rc; | 371 | struct dvb_usb_rc rc; |
375 | struct work_struct probe_work; | ||
376 | pid_t work_pid; | ||
377 | int powered; | 372 | int powered; |
378 | 373 | ||
379 | /* locking */ | 374 | /* locking */ |
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 19f6737d9817..8a054d66e708 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | |||
@@ -833,20 +833,44 @@ err: | |||
833 | return ret; | 833 | return ret; |
834 | } | 834 | } |
835 | 835 | ||
836 | /* | 836 | int dvb_usbv2_probe(struct usb_interface *intf, |
837 | * udev, which is used for the firmware downloading, requires we cannot | 837 | const struct usb_device_id *id) |
838 | * block during module_init(). module_init() calls USB probe() which | ||
839 | * is this routine. Due to that we delay actual operation using workqueue | ||
840 | * and return always success here. | ||
841 | */ | ||
842 | static void dvb_usbv2_init_work(struct work_struct *work) | ||
843 | { | 838 | { |
844 | int ret; | 839 | int ret; |
845 | struct dvb_usb_device *d = | 840 | struct dvb_usb_device *d; |
846 | container_of(work, struct dvb_usb_device, probe_work); | 841 | struct usb_device *udev = interface_to_usbdev(intf); |
842 | struct dvb_usb_driver_info *driver_info = | ||
843 | (struct dvb_usb_driver_info *) id->driver_info; | ||
844 | |||
845 | dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, | ||
846 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
847 | |||
848 | if (!id->driver_info) { | ||
849 | dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); | ||
850 | ret = -ENODEV; | ||
851 | goto err; | ||
852 | } | ||
853 | |||
854 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); | ||
855 | if (!d) { | ||
856 | dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | ||
857 | ret = -ENOMEM; | ||
858 | goto err; | ||
859 | } | ||
847 | 860 | ||
848 | d->work_pid = current->pid; | 861 | d->name = driver_info->name; |
849 | dev_dbg(&d->udev->dev, "%s: work_pid=%d\n", __func__, d->work_pid); | 862 | d->rc_map = driver_info->rc_map; |
863 | d->udev = udev; | ||
864 | d->props = driver_info->props; | ||
865 | |||
866 | if (intf->cur_altsetting->desc.bInterfaceNumber != | ||
867 | d->props->bInterfaceNumber) { | ||
868 | ret = -ENODEV; | ||
869 | goto err_free_all; | ||
870 | } | ||
871 | |||
872 | mutex_init(&d->usb_mutex); | ||
873 | mutex_init(&d->i2c_mutex); | ||
850 | 874 | ||
851 | if (d->props->size_of_priv) { | 875 | if (d->props->size_of_priv) { |
852 | d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); | 876 | d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); |
@@ -854,7 +878,7 @@ static void dvb_usbv2_init_work(struct work_struct *work) | |||
854 | dev_err(&d->udev->dev, "%s: kzalloc() failed\n", | 878 | dev_err(&d->udev->dev, "%s: kzalloc() failed\n", |
855 | KBUILD_MODNAME); | 879 | KBUILD_MODNAME); |
856 | ret = -ENOMEM; | 880 | ret = -ENOMEM; |
857 | goto err_usb_driver_release_interface; | 881 | goto err_free_all; |
858 | } | 882 | } |
859 | } | 883 | } |
860 | 884 | ||
@@ -884,20 +908,12 @@ static void dvb_usbv2_init_work(struct work_struct *work) | |||
884 | * device. As 'new' device is warm we should | 908 | * device. As 'new' device is warm we should |
885 | * never go here again. | 909 | * never go here again. |
886 | */ | 910 | */ |
887 | return; | 911 | goto exit; |
888 | } else { | 912 | } else { |
889 | /* | 913 | goto err_free_all; |
890 | * Unexpected error. We must unregister driver | ||
891 | * manually from the device, because device is | ||
892 | * already register by returning from probe() | ||
893 | * with success. usb_driver_release_interface() | ||
894 | * finally calls disconnect() in order to free | ||
895 | * resources. | ||
896 | */ | ||
897 | goto err_usb_driver_release_interface; | ||
898 | } | 914 | } |
899 | } else { | 915 | } else { |
900 | goto err_usb_driver_release_interface; | 916 | goto err_free_all; |
901 | } | 917 | } |
902 | } | 918 | } |
903 | 919 | ||
@@ -906,73 +922,17 @@ static void dvb_usbv2_init_work(struct work_struct *work) | |||
906 | 922 | ||
907 | ret = dvb_usbv2_init(d); | 923 | ret = dvb_usbv2_init(d); |
908 | if (ret < 0) | 924 | if (ret < 0) |
909 | goto err_usb_driver_release_interface; | 925 | goto err_free_all; |
910 | 926 | ||
911 | dev_info(&d->udev->dev, | 927 | dev_info(&d->udev->dev, |
912 | "%s: '%s' successfully initialized and connected\n", | 928 | "%s: '%s' successfully initialized and connected\n", |
913 | KBUILD_MODNAME, d->name); | 929 | KBUILD_MODNAME, d->name); |
914 | 930 | exit: | |
915 | return; | ||
916 | err_usb_driver_release_interface: | ||
917 | dev_info(&d->udev->dev, "%s: '%s' error while loading driver (%d)\n", | ||
918 | KBUILD_MODNAME, d->name, ret); | ||
919 | usb_driver_release_interface(to_usb_driver(d->intf->dev.driver), | ||
920 | d->intf); | ||
921 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
922 | return; | ||
923 | } | ||
924 | |||
925 | int dvb_usbv2_probe(struct usb_interface *intf, | ||
926 | const struct usb_device_id *id) | ||
927 | { | ||
928 | int ret; | ||
929 | struct dvb_usb_device *d; | ||
930 | struct usb_device *udev = interface_to_usbdev(intf); | ||
931 | struct dvb_usb_driver_info *driver_info = | ||
932 | (struct dvb_usb_driver_info *) id->driver_info; | ||
933 | |||
934 | dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, | ||
935 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
936 | |||
937 | if (!id->driver_info) { | ||
938 | dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); | ||
939 | ret = -ENODEV; | ||
940 | goto err; | ||
941 | } | ||
942 | |||
943 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); | ||
944 | if (!d) { | ||
945 | dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | ||
946 | ret = -ENOMEM; | ||
947 | goto err; | ||
948 | } | ||
949 | |||
950 | d->name = driver_info->name; | ||
951 | d->rc_map = driver_info->rc_map; | ||
952 | d->udev = udev; | ||
953 | d->intf = intf; | ||
954 | d->props = driver_info->props; | ||
955 | |||
956 | if (d->intf->cur_altsetting->desc.bInterfaceNumber != | ||
957 | d->props->bInterfaceNumber) { | ||
958 | ret = -ENODEV; | ||
959 | goto err_kfree; | ||
960 | } | ||
961 | |||
962 | mutex_init(&d->usb_mutex); | ||
963 | mutex_init(&d->i2c_mutex); | ||
964 | INIT_WORK(&d->probe_work, dvb_usbv2_init_work); | ||
965 | usb_set_intfdata(intf, d); | 931 | usb_set_intfdata(intf, d); |
966 | ret = schedule_work(&d->probe_work); | ||
967 | if (ret < 0) { | ||
968 | dev_err(&d->udev->dev, "%s: schedule_work() failed\n", | ||
969 | KBUILD_MODNAME); | ||
970 | goto err_kfree; | ||
971 | } | ||
972 | 932 | ||
973 | return 0; | 933 | return 0; |
974 | err_kfree: | 934 | err_free_all: |
975 | kfree(d); | 935 | dvb_usbv2_exit(d); |
976 | err: | 936 | err: |
977 | dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); | 937 | dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); |
978 | return ret; | 938 | return ret; |
@@ -984,12 +944,8 @@ void dvb_usbv2_disconnect(struct usb_interface *intf) | |||
984 | struct dvb_usb_device *d = usb_get_intfdata(intf); | 944 | struct dvb_usb_device *d = usb_get_intfdata(intf); |
985 | const char *name = d->name; | 945 | const char *name = d->name; |
986 | struct device dev = d->udev->dev; | 946 | struct device dev = d->udev->dev; |
987 | dev_dbg(&d->udev->dev, "%s: pid=%d work_pid=%d\n", __func__, | 947 | dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, |
988 | current->pid, d->work_pid); | 948 | intf->cur_altsetting->desc.bInterfaceNumber); |
989 | |||
990 | /* ensure initialization work is finished until release resources */ | ||
991 | if (d->work_pid != current->pid) | ||
992 | cancel_work_sync(&d->probe_work); | ||
993 | 949 | ||
994 | if (d->props->exit) | 950 | if (d->props->exit) |
995 | d->props->exit(d); | 951 | d->props->exit(d); |
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index b3fd0ffa3c3f..f674dc024d06 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c | |||
@@ -1225,7 +1225,7 @@ static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) | |||
1225 | usb_reset_configuration(d->udev); | 1225 | usb_reset_configuration(d->udev); |
1226 | 1226 | ||
1227 | usb_set_interface(d->udev, | 1227 | usb_set_interface(d->udev, |
1228 | d->intf->cur_altsetting->desc.bInterfaceNumber, 1); | 1228 | d->props->bInterfaceNumber, 1); |
1229 | 1229 | ||
1230 | st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; | 1230 | st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; |
1231 | 1231 | ||
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index f08136052f9c..829323e42ca0 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c | |||
@@ -3589,6 +3589,8 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
3589 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7790P) }, | 3589 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7790P) }, |
3590 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE8096P) }, | 3590 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE8096P) }, |
3591 | /* 80 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_2) }, | 3591 | /* 80 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_2) }, |
3592 | { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E) }, | ||
3593 | { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E_SE) }, | ||
3592 | { 0 } /* Terminating entry */ | 3594 | { 0 } /* Terminating entry */ |
3593 | }; | 3595 | }; |
3594 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 3596 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -3993,12 +3995,20 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
3993 | } | 3995 | } |
3994 | }, | 3996 | }, |
3995 | 3997 | ||
3996 | .num_device_descs = 1, | 3998 | .num_device_descs = 3, |
3997 | .devices = { | 3999 | .devices = { |
3998 | { "Hauppauge Nova-TD Stick (52009)", | 4000 | { "Hauppauge Nova-TD Stick (52009)", |
3999 | { &dib0700_usb_id_table[35], NULL }, | 4001 | { &dib0700_usb_id_table[35], NULL }, |
4000 | { NULL }, | 4002 | { NULL }, |
4001 | }, | 4003 | }, |
4004 | { "PCTV 2002e", | ||
4005 | { &dib0700_usb_id_table[81], NULL }, | ||
4006 | { NULL }, | ||
4007 | }, | ||
4008 | { "PCTV 2002e SE", | ||
4009 | { &dib0700_usb_id_table[82], NULL }, | ||
4010 | { NULL }, | ||
4011 | }, | ||
4002 | }, | 4012 | }, |
4003 | 4013 | ||
4004 | .rc.core = { | 4014 | .rc.core = { |
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c index c2b635d6a17a..0306cb778df4 100644 --- a/drivers/media/usb/dvb-usb/m920x.c +++ b/drivers/media/usb/dvb-usb/m920x.c | |||
@@ -1212,7 +1212,7 @@ static struct dvb_usb_device_properties vp7049_properties = { | |||
1212 | .rc_interval = 150, | 1212 | .rc_interval = 150, |
1213 | .rc_codes = RC_MAP_TWINHAN_VP1027_DVBS, | 1213 | .rc_codes = RC_MAP_TWINHAN_VP1027_DVBS, |
1214 | .rc_query = m920x_rc_core_query, | 1214 | .rc_query = m920x_rc_core_query, |
1215 | .allowed_protos = RC_TYPE_UNKNOWN, | 1215 | .allowed_protos = RC_BIT_UNKNOWN, |
1216 | }, | 1216 | }, |
1217 | 1217 | ||
1218 | .size_of_priv = sizeof(struct m920x_state), | 1218 | .size_of_priv = sizeof(struct m920x_state), |
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 1a577ed8ea0c..9d103344f34a 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c | |||
@@ -1008,6 +1008,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1008 | else | 1008 | else |
1009 | f->fmt.pix.field = dev->interlaced ? | 1009 | f->fmt.pix.field = dev->interlaced ? |
1010 | V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; | 1010 | V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; |
1011 | f->fmt.pix.priv = 0; | ||
1011 | 1012 | ||
1012 | return 0; | 1013 | return 0; |
1013 | } | 1014 | } |
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig index 6345f9331e7f..4f0c6d566c85 100644 --- a/drivers/media/usb/gspca/Kconfig +++ b/drivers/media/usb/gspca/Kconfig | |||
@@ -338,6 +338,15 @@ config USB_GSPCA_STK014 | |||
338 | To compile this driver as a module, choose M here: the | 338 | To compile this driver as a module, choose M here: the |
339 | module will be called gspca_stk014. | 339 | module will be called gspca_stk014. |
340 | 340 | ||
341 | config USB_GSPCA_STK1135 | ||
342 | tristate "Syntek STK1135 USB Camera Driver" | ||
343 | depends on VIDEO_V4L2 && USB_GSPCA | ||
344 | help | ||
345 | Say Y here if you want support for cameras based on the STK1135 chip. | ||
346 | |||
347 | To compile this driver as a module, choose M here: the | ||
348 | module will be called gspca_stk1135. | ||
349 | |||
341 | config USB_GSPCA_STV0680 | 350 | config USB_GSPCA_STV0680 |
342 | tristate "STV0680 USB Camera Driver" | 351 | tristate "STV0680 USB Camera Driver" |
343 | depends on VIDEO_V4L2 && USB_GSPCA | 352 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/usb/gspca/Makefile b/drivers/media/usb/gspca/Makefile index c901da0bd657..5855131ab8b6 100644 --- a/drivers/media/usb/gspca/Makefile +++ b/drivers/media/usb/gspca/Makefile | |||
@@ -34,6 +34,7 @@ obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o | |||
34 | obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o | 34 | obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o |
35 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o | 35 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o |
36 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o | 36 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o |
37 | obj-$(CONFIG_USB_GSPCA_STK1135) += gspca_stk1135.o | ||
37 | obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o | 38 | obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o |
38 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o | 39 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o |
39 | obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o | 40 | obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o |
@@ -78,6 +79,7 @@ gspca_sq905-objs := sq905.o | |||
78 | gspca_sq905c-objs := sq905c.o | 79 | gspca_sq905c-objs := sq905c.o |
79 | gspca_sq930x-objs := sq930x.o | 80 | gspca_sq930x-objs := sq930x.o |
80 | gspca_stk014-objs := stk014.o | 81 | gspca_stk014-objs := stk014.o |
82 | gspca_stk1135-objs := stk1135.o | ||
81 | gspca_stv0680-objs := stv0680.o | 83 | gspca_stv0680-objs := stv0680.o |
82 | gspca_sunplus-objs := sunplus.o | 84 | gspca_sunplus-objs := sunplus.o |
83 | gspca_t613-objs := t613.o | 85 | gspca_t613-objs := t613.o |
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index b7ae8721b847..048507b27bb2 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c | |||
@@ -1266,6 +1266,7 @@ static void gspca_release(struct v4l2_device *v4l2_device) | |||
1266 | static int dev_open(struct file *file) | 1266 | static int dev_open(struct file *file) |
1267 | { | 1267 | { |
1268 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1268 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1269 | int ret; | ||
1269 | 1270 | ||
1270 | PDEBUG(D_STREAM, "[%s] open", current->comm); | 1271 | PDEBUG(D_STREAM, "[%s] open", current->comm); |
1271 | 1272 | ||
@@ -1273,7 +1274,10 @@ static int dev_open(struct file *file) | |||
1273 | if (!try_module_get(gspca_dev->module)) | 1274 | if (!try_module_get(gspca_dev->module)) |
1274 | return -ENODEV; | 1275 | return -ENODEV; |
1275 | 1276 | ||
1276 | return v4l2_fh_open(file); | 1277 | ret = v4l2_fh_open(file); |
1278 | if (ret) | ||
1279 | module_put(gspca_dev->module); | ||
1280 | return ret; | ||
1277 | } | 1281 | } |
1278 | 1282 | ||
1279 | static int dev_close(struct file *file) | 1283 | static int dev_close(struct file *file) |
diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c index a3958ee86816..8937d79fd176 100644 --- a/drivers/media/usb/gspca/ov519.c +++ b/drivers/media/usb/gspca/ov519.c | |||
@@ -75,6 +75,8 @@ struct sd { | |||
75 | struct v4l2_ctrl *brightness; | 75 | struct v4l2_ctrl *brightness; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | u8 revision; | ||
79 | |||
78 | u8 packet_nr; | 80 | u8 packet_nr; |
79 | 81 | ||
80 | char bridge; | 82 | char bridge; |
@@ -3080,8 +3082,8 @@ static void ov518_configure(struct gspca_dev *gspca_dev) | |||
3080 | }; | 3082 | }; |
3081 | 3083 | ||
3082 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ | 3084 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ |
3083 | PDEBUG(D_PROBE, "Device revision %d", | 3085 | sd->revision = reg_r(sd, R51x_SYS_CUST_ID) & 0x1f; |
3084 | 0x1f & reg_r(sd, R51x_SYS_CUST_ID)); | 3086 | PDEBUG(D_PROBE, "Device revision %d", sd->revision); |
3085 | 3087 | ||
3086 | write_regvals(sd, init_518, ARRAY_SIZE(init_518)); | 3088 | write_regvals(sd, init_518, ARRAY_SIZE(init_518)); |
3087 | 3089 | ||
@@ -3657,7 +3659,11 @@ static void ov518_mode_init_regs(struct sd *sd) | |||
3657 | reg_w(sd, 0x2f, 0x80); | 3659 | reg_w(sd, 0x2f, 0x80); |
3658 | 3660 | ||
3659 | /******** Set the framerate ********/ | 3661 | /******** Set the framerate ********/ |
3660 | sd->clockdiv = 1; | 3662 | if (sd->bridge == BRIDGE_OV518PLUS && sd->revision == 0 && |
3663 | sd->sensor == SEN_OV7620AE) | ||
3664 | sd->clockdiv = 0; | ||
3665 | else | ||
3666 | sd->clockdiv = 1; | ||
3661 | 3667 | ||
3662 | /* Mode independent, but framerate dependent, regs */ | 3668 | /* Mode independent, but framerate dependent, regs */ |
3663 | /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ | 3669 | /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ |
@@ -3668,12 +3674,24 @@ static void ov518_mode_init_regs(struct sd *sd) | |||
3668 | if (sd->bridge == BRIDGE_OV518PLUS) { | 3674 | if (sd->bridge == BRIDGE_OV518PLUS) { |
3669 | switch (sd->sensor) { | 3675 | switch (sd->sensor) { |
3670 | case SEN_OV7620AE: | 3676 | case SEN_OV7620AE: |
3671 | if (sd->gspca_dev.width == 320) { | 3677 | /* |
3672 | reg_w(sd, 0x20, 0x00); | 3678 | * HdG: 640x480 needs special handling on device |
3673 | reg_w(sd, 0x21, 0x19); | 3679 | * revision 2, we check for device revison > 0 to |
3674 | } else { | 3680 | * avoid regressions, as we don't know the correct |
3681 | * thing todo for revision 1. | ||
3682 | * | ||
3683 | * Also this likely means we don't need to | ||
3684 | * differentiate between the OV7620 and OV7620AE, | ||
3685 | * earlier testing hitting this same problem likely | ||
3686 | * happened to be with revision < 2 cams using an | ||
3687 | * OV7620 and revision 2 cams using an OV7620AE. | ||
3688 | */ | ||
3689 | if (sd->revision > 0 && sd->gspca_dev.width == 640) { | ||
3675 | reg_w(sd, 0x20, 0x60); | 3690 | reg_w(sd, 0x20, 0x60); |
3676 | reg_w(sd, 0x21, 0x1f); | 3691 | reg_w(sd, 0x21, 0x1f); |
3692 | } else { | ||
3693 | reg_w(sd, 0x20, 0x00); | ||
3694 | reg_w(sd, 0x21, 0x19); | ||
3677 | } | 3695 | } |
3678 | break; | 3696 | break; |
3679 | case SEN_OV7620: | 3697 | case SEN_OV7620: |
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c index 2e28c81a03ab..03a33c46ca2c 100644 --- a/drivers/media/usb/gspca/ov534.c +++ b/drivers/media/usb/gspca/ov534.c | |||
@@ -1305,8 +1305,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1305 | ov534_set_led(gspca_dev, 1); | 1305 | ov534_set_led(gspca_dev, 1); |
1306 | sccb_w_array(gspca_dev, sensor_init[sd->sensor].val, | 1306 | sccb_w_array(gspca_dev, sensor_init[sd->sensor].val, |
1307 | sensor_init[sd->sensor].len); | 1307 | sensor_init[sd->sensor].len); |
1308 | if (sd->sensor == SENSOR_OV767x) | 1308 | |
1309 | sd_start(gspca_dev); | ||
1310 | sd_stopN(gspca_dev); | 1309 | sd_stopN(gspca_dev); |
1311 | /* set_frame_rate(gspca_dev); */ | 1310 | /* set_frame_rate(gspca_dev); */ |
1312 | 1311 | ||
diff --git a/drivers/media/usb/gspca/stk1135.c b/drivers/media/usb/gspca/stk1135.c new file mode 100644 index 000000000000..585868835ace --- /dev/null +++ b/drivers/media/usb/gspca/stk1135.c | |||
@@ -0,0 +1,685 @@ | |||
1 | /* | ||
2 | * Syntek STK1135 subdriver | ||
3 | * | ||
4 | * Copyright (c) 2013 Ondrej Zary | ||
5 | * | ||
6 | * Based on Syntekdriver (stk11xx) by Nicolas VIVIEN: | ||
7 | * http://syntekdriver.sourceforge.net | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
25 | |||
26 | #define MODULE_NAME "stk1135" | ||
27 | |||
28 | #include "gspca.h" | ||
29 | #include "stk1135.h" | ||
30 | |||
31 | MODULE_AUTHOR("Ondrej Zary"); | ||
32 | MODULE_DESCRIPTION("Syntek STK1135 USB Camera Driver"); | ||
33 | MODULE_LICENSE("GPL"); | ||
34 | |||
35 | |||
36 | /* specific webcam descriptor */ | ||
37 | struct sd { | ||
38 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
39 | |||
40 | u8 pkt_seq; | ||
41 | u8 sensor_page; | ||
42 | |||
43 | bool flip_status; | ||
44 | u8 flip_debounce; | ||
45 | |||
46 | struct v4l2_ctrl *hflip; | ||
47 | struct v4l2_ctrl *vflip; | ||
48 | }; | ||
49 | |||
50 | static const struct v4l2_pix_format stk1135_modes[] = { | ||
51 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
52 | .bytesperline = 160, | ||
53 | .sizeimage = 160 * 120, | ||
54 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
55 | {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
56 | .bytesperline = 176, | ||
57 | .sizeimage = 176 * 144, | ||
58 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
59 | {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
60 | .bytesperline = 320, | ||
61 | .sizeimage = 320 * 240, | ||
62 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
63 | {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
64 | .bytesperline = 352, | ||
65 | .sizeimage = 352 * 288, | ||
66 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
67 | {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
68 | .bytesperline = 640, | ||
69 | .sizeimage = 640 * 480, | ||
70 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
71 | {720, 576, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
72 | .bytesperline = 720, | ||
73 | .sizeimage = 720 * 576, | ||
74 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
75 | {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
76 | .bytesperline = 800, | ||
77 | .sizeimage = 800 * 600, | ||
78 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
79 | {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
80 | .bytesperline = 1024, | ||
81 | .sizeimage = 1024 * 768, | ||
82 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
83 | {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
84 | .bytesperline = 1280, | ||
85 | .sizeimage = 1280 * 1024, | ||
86 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
87 | }; | ||
88 | |||
89 | /* -- read a register -- */ | ||
90 | static u8 reg_r(struct gspca_dev *gspca_dev, u16 index) | ||
91 | { | ||
92 | struct usb_device *dev = gspca_dev->dev; | ||
93 | int ret; | ||
94 | |||
95 | if (gspca_dev->usb_err < 0) | ||
96 | return 0; | ||
97 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
98 | 0x00, | ||
99 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
100 | 0x00, | ||
101 | index, | ||
102 | gspca_dev->usb_buf, 1, | ||
103 | 500); | ||
104 | |||
105 | PDEBUG(D_USBI, "reg_r 0x%x=0x%02x", index, gspca_dev->usb_buf[0]); | ||
106 | if (ret < 0) { | ||
107 | pr_err("reg_r 0x%x err %d\n", index, ret); | ||
108 | gspca_dev->usb_err = ret; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | return gspca_dev->usb_buf[0]; | ||
113 | } | ||
114 | |||
115 | /* -- write a register -- */ | ||
116 | static void reg_w(struct gspca_dev *gspca_dev, u16 index, u8 val) | ||
117 | { | ||
118 | int ret; | ||
119 | struct usb_device *dev = gspca_dev->dev; | ||
120 | |||
121 | if (gspca_dev->usb_err < 0) | ||
122 | return; | ||
123 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
124 | 0x01, | ||
125 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
126 | val, | ||
127 | index, | ||
128 | NULL, | ||
129 | 0, | ||
130 | 500); | ||
131 | PDEBUG(D_USBO, "reg_w 0x%x:=0x%02x", index, val); | ||
132 | if (ret < 0) { | ||
133 | pr_err("reg_w 0x%x err %d\n", index, ret); | ||
134 | gspca_dev->usb_err = ret; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static void reg_w_mask(struct gspca_dev *gspca_dev, u16 index, u8 val, u8 mask) | ||
139 | { | ||
140 | val = (reg_r(gspca_dev, index) & ~mask) | (val & mask); | ||
141 | reg_w(gspca_dev, index, val); | ||
142 | } | ||
143 | |||
144 | /* this function is called at probe time */ | ||
145 | static int sd_config(struct gspca_dev *gspca_dev, | ||
146 | const struct usb_device_id *id) | ||
147 | { | ||
148 | gspca_dev->cam.cam_mode = stk1135_modes; | ||
149 | gspca_dev->cam.nmodes = ARRAY_SIZE(stk1135_modes); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int stk1135_serial_wait_ready(struct gspca_dev *gspca_dev) | ||
154 | { | ||
155 | int i = 0; | ||
156 | u8 val; | ||
157 | |||
158 | do { | ||
159 | val = reg_r(gspca_dev, STK1135_REG_SICTL + 1); | ||
160 | if (i++ > 500) { /* maximum retry count */ | ||
161 | pr_err("serial bus timeout: status=0x%02x\n", val); | ||
162 | return -1; | ||
163 | } | ||
164 | /* repeat if BUSY or WRITE/READ not finished */ | ||
165 | } while ((val & 0x10) || !(val & 0x05)); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static u8 sensor_read_8(struct gspca_dev *gspca_dev, u8 addr) | ||
171 | { | ||
172 | reg_w(gspca_dev, STK1135_REG_SBUSR, addr); | ||
173 | /* begin read */ | ||
174 | reg_w(gspca_dev, STK1135_REG_SICTL, 0x20); | ||
175 | /* wait until finished */ | ||
176 | if (stk1135_serial_wait_ready(gspca_dev)) { | ||
177 | pr_err("Sensor read failed\n"); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | return reg_r(gspca_dev, STK1135_REG_SBUSR + 1); | ||
182 | } | ||
183 | |||
184 | static u16 sensor_read_16(struct gspca_dev *gspca_dev, u8 addr) | ||
185 | { | ||
186 | return (sensor_read_8(gspca_dev, addr) << 8) | | ||
187 | sensor_read_8(gspca_dev, 0xf1); | ||
188 | } | ||
189 | |||
190 | static void sensor_write_8(struct gspca_dev *gspca_dev, u8 addr, u8 data) | ||
191 | { | ||
192 | /* load address and data registers */ | ||
193 | reg_w(gspca_dev, STK1135_REG_SBUSW, addr); | ||
194 | reg_w(gspca_dev, STK1135_REG_SBUSW + 1, data); | ||
195 | /* begin write */ | ||
196 | reg_w(gspca_dev, STK1135_REG_SICTL, 0x01); | ||
197 | /* wait until finished */ | ||
198 | if (stk1135_serial_wait_ready(gspca_dev)) { | ||
199 | pr_err("Sensor write failed\n"); | ||
200 | return; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | static void sensor_write_16(struct gspca_dev *gspca_dev, u8 addr, u16 data) | ||
205 | { | ||
206 | sensor_write_8(gspca_dev, addr, data >> 8); | ||
207 | sensor_write_8(gspca_dev, 0xf1, data & 0xff); | ||
208 | } | ||
209 | |||
210 | static void sensor_set_page(struct gspca_dev *gspca_dev, u8 page) | ||
211 | { | ||
212 | struct sd *sd = (struct sd *) gspca_dev; | ||
213 | |||
214 | if (page != sd->sensor_page) { | ||
215 | sensor_write_16(gspca_dev, 0xf0, page); | ||
216 | sd->sensor_page = page; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static u16 sensor_read(struct gspca_dev *gspca_dev, u16 reg) | ||
221 | { | ||
222 | sensor_set_page(gspca_dev, reg >> 8); | ||
223 | return sensor_read_16(gspca_dev, reg & 0xff); | ||
224 | } | ||
225 | |||
226 | static void sensor_write(struct gspca_dev *gspca_dev, u16 reg, u16 val) | ||
227 | { | ||
228 | sensor_set_page(gspca_dev, reg >> 8); | ||
229 | sensor_write_16(gspca_dev, reg & 0xff, val); | ||
230 | } | ||
231 | |||
232 | static void sensor_write_mask(struct gspca_dev *gspca_dev, | ||
233 | u16 reg, u16 val, u16 mask) | ||
234 | { | ||
235 | val = (sensor_read(gspca_dev, reg) & ~mask) | (val & mask); | ||
236 | sensor_write(gspca_dev, reg, val); | ||
237 | } | ||
238 | |||
239 | struct sensor_val { | ||
240 | u16 reg; | ||
241 | u16 val; | ||
242 | }; | ||
243 | |||
244 | /* configure MT9M112 sensor */ | ||
245 | static void stk1135_configure_mt9m112(struct gspca_dev *gspca_dev) | ||
246 | { | ||
247 | static const struct sensor_val cfg[] = { | ||
248 | /* restart&reset, chip enable, reserved */ | ||
249 | { 0x00d, 0x000b }, { 0x00d, 0x0008 }, { 0x035, 0x0022 }, | ||
250 | /* mode ctl: AWB on, AE both, clip aper corr, defect corr, AE */ | ||
251 | { 0x106, 0x700e }, | ||
252 | |||
253 | { 0x2dd, 0x18e0 }, /* B-R thresholds, */ | ||
254 | |||
255 | /* AWB */ | ||
256 | { 0x21f, 0x0180 }, /* Cb and Cr limits */ | ||
257 | { 0x220, 0xc814 }, { 0x221, 0x8080 }, /* lum limits, RGB gain */ | ||
258 | { 0x222, 0xa078 }, { 0x223, 0xa078 }, /* R, B limit */ | ||
259 | { 0x224, 0x5f20 }, { 0x228, 0xea02 }, /* mtx adj lim, adv ctl */ | ||
260 | { 0x229, 0x867a }, /* wide gates */ | ||
261 | |||
262 | /* Color correction */ | ||
263 | /* imager gains base, delta, delta signs */ | ||
264 | { 0x25e, 0x594c }, { 0x25f, 0x4d51 }, { 0x260, 0x0002 }, | ||
265 | /* AWB adv ctl 2, gain offs */ | ||
266 | { 0x2ef, 0x0008 }, { 0x2f2, 0x0000 }, | ||
267 | /* base matrix signs, scale K1-5, K6-9 */ | ||
268 | { 0x202, 0x00ee }, { 0x203, 0x3923 }, { 0x204, 0x0724 }, | ||
269 | /* base matrix coef */ | ||
270 | { 0x209, 0x00cd }, { 0x20a, 0x0093 }, { 0x20b, 0x0004 },/*K1-3*/ | ||
271 | { 0x20c, 0x005c }, { 0x20d, 0x00d9 }, { 0x20e, 0x0053 },/*K4-6*/ | ||
272 | { 0x20f, 0x0008 }, { 0x210, 0x0091 }, { 0x211, 0x00cf },/*K7-9*/ | ||
273 | { 0x215, 0x0000 }, /* delta mtx signs */ | ||
274 | /* delta matrix coef */ | ||
275 | { 0x216, 0x0000 }, { 0x217, 0x0000 }, { 0x218, 0x0000 },/*D1-3*/ | ||
276 | { 0x219, 0x0000 }, { 0x21a, 0x0000 }, { 0x21b, 0x0000 },/*D4-6*/ | ||
277 | { 0x21c, 0x0000 }, { 0x21d, 0x0000 }, { 0x21e, 0x0000 },/*D7-9*/ | ||
278 | /* enable & disable manual WB to apply color corr. settings */ | ||
279 | { 0x106, 0xf00e }, { 0x106, 0x700e }, | ||
280 | |||
281 | /* Lens shading correction */ | ||
282 | { 0x180, 0x0007 }, /* control */ | ||
283 | /* vertical knee 0, 2+1, 4+3 */ | ||
284 | { 0x181, 0xde13 }, { 0x182, 0xebe2 }, { 0x183, 0x00f6 }, /* R */ | ||
285 | { 0x184, 0xe114 }, { 0x185, 0xeadd }, { 0x186, 0xfdf6 }, /* G */ | ||
286 | { 0x187, 0xe511 }, { 0x188, 0xede6 }, { 0x189, 0xfbf7 }, /* B */ | ||
287 | /* horizontal knee 0, 2+1, 4+3, 5 */ | ||
288 | { 0x18a, 0xd613 }, { 0x18b, 0xedec }, /* R .. */ | ||
289 | { 0x18c, 0xf9f2 }, { 0x18d, 0x0000 }, /* .. R */ | ||
290 | { 0x18e, 0xd815 }, { 0x18f, 0xe9ea }, /* G .. */ | ||
291 | { 0x190, 0xf9f1 }, { 0x191, 0x0002 }, /* .. G */ | ||
292 | { 0x192, 0xde10 }, { 0x193, 0xefef }, /* B .. */ | ||
293 | { 0x194, 0xfbf4 }, { 0x195, 0x0002 }, /* .. B */ | ||
294 | /* vertical knee 6+5, 8+7 */ | ||
295 | { 0x1b6, 0x0e06 }, { 0x1b7, 0x2713 }, /* R */ | ||
296 | { 0x1b8, 0x1106 }, { 0x1b9, 0x2713 }, /* G */ | ||
297 | { 0x1ba, 0x0c03 }, { 0x1bb, 0x2a0f }, /* B */ | ||
298 | /* horizontal knee 7+6, 9+8, 10 */ | ||
299 | { 0x1bc, 0x1208 }, { 0x1bd, 0x1a16 }, { 0x1be, 0x0022 }, /* R */ | ||
300 | { 0x1bf, 0x150a }, { 0x1c0, 0x1c1a }, { 0x1c1, 0x002d }, /* G */ | ||
301 | { 0x1c2, 0x1109 }, { 0x1c3, 0x1414 }, { 0x1c4, 0x002a }, /* B */ | ||
302 | { 0x106, 0x740e }, /* enable lens shading correction */ | ||
303 | |||
304 | /* Gamma correction - context A */ | ||
305 | { 0x153, 0x0b03 }, { 0x154, 0x4722 }, { 0x155, 0xac82 }, | ||
306 | { 0x156, 0xdac7 }, { 0x157, 0xf5e9 }, { 0x158, 0xff00 }, | ||
307 | /* Gamma correction - context B */ | ||
308 | { 0x1dc, 0x0b03 }, { 0x1dd, 0x4722 }, { 0x1de, 0xac82 }, | ||
309 | { 0x1df, 0xdac7 }, { 0x1e0, 0xf5e9 }, { 0x1e1, 0xff00 }, | ||
310 | |||
311 | /* output format: RGB, invert output pixclock, output bayer */ | ||
312 | { 0x13a, 0x4300 }, { 0x19b, 0x4300 }, /* for context A, B */ | ||
313 | { 0x108, 0x0180 }, /* format control - enable bayer row flip */ | ||
314 | |||
315 | { 0x22f, 0xd100 }, { 0x29c, 0xd100 }, /* AE A, B */ | ||
316 | |||
317 | /* default prg conf, prg ctl - by 0x2d2, prg advance - PA1 */ | ||
318 | { 0x2d2, 0x0000 }, { 0x2cc, 0x0004 }, { 0x2cb, 0x0001 }, | ||
319 | |||
320 | { 0x22e, 0x0c3c }, { 0x267, 0x1010 }, /* AE tgt ctl, gain lim */ | ||
321 | |||
322 | /* PLL */ | ||
323 | { 0x065, 0xa000 }, /* clk ctl - enable PLL (clear bit 14) */ | ||
324 | { 0x066, 0x2003 }, { 0x067, 0x0501 }, /* PLL M=128, N=3, P=1 */ | ||
325 | { 0x065, 0x2000 }, /* disable PLL bypass (clear bit 15) */ | ||
326 | |||
327 | { 0x005, 0x01b8 }, { 0x007, 0x00d8 }, /* horiz blanking B, A */ | ||
328 | |||
329 | /* AE line size, shutter delay limit */ | ||
330 | { 0x239, 0x06c0 }, { 0x23b, 0x040e }, /* for context A */ | ||
331 | { 0x23a, 0x06c0 }, { 0x23c, 0x0564 }, /* for context B */ | ||
332 | /* shutter width basis 60Hz, 50Hz */ | ||
333 | { 0x257, 0x0208 }, { 0x258, 0x0271 }, /* for context A */ | ||
334 | { 0x259, 0x0209 }, { 0x25a, 0x0271 }, /* for context B */ | ||
335 | |||
336 | { 0x25c, 0x120d }, { 0x25d, 0x1712 }, /* flicker 60Hz, 50Hz */ | ||
337 | { 0x264, 0x5e1c }, /* reserved */ | ||
338 | /* flicker, AE gain limits, gain zone limits */ | ||
339 | { 0x25b, 0x0003 }, { 0x236, 0x7810 }, { 0x237, 0x8304 }, | ||
340 | |||
341 | { 0x008, 0x0021 }, /* vert blanking A */ | ||
342 | }; | ||
343 | int i; | ||
344 | u16 width, height; | ||
345 | |||
346 | for (i = 0; i < ARRAY_SIZE(cfg); i++) | ||
347 | sensor_write(gspca_dev, cfg[i].reg, cfg[i].val); | ||
348 | |||
349 | /* set output size */ | ||
350 | width = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].width; | ||
351 | height = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].height; | ||
352 | if (width <= 640) { /* use context A (half readout speed by default) */ | ||
353 | sensor_write(gspca_dev, 0x1a7, width); | ||
354 | sensor_write(gspca_dev, 0x1aa, height); | ||
355 | /* set read mode context A */ | ||
356 | sensor_write(gspca_dev, 0x0c8, 0x0000); | ||
357 | /* set resize, read mode, vblank, hblank context A */ | ||
358 | sensor_write(gspca_dev, 0x2c8, 0x0000); | ||
359 | } else { /* use context B (full readout speed by default) */ | ||
360 | sensor_write(gspca_dev, 0x1a1, width); | ||
361 | sensor_write(gspca_dev, 0x1a4, height); | ||
362 | /* set read mode context B */ | ||
363 | sensor_write(gspca_dev, 0x0c8, 0x0008); | ||
364 | /* set resize, read mode, vblank, hblank context B */ | ||
365 | sensor_write(gspca_dev, 0x2c8, 0x040b); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | static void stk1135_configure_clock(struct gspca_dev *gspca_dev) | ||
370 | { | ||
371 | /* configure SCLKOUT */ | ||
372 | reg_w(gspca_dev, STK1135_REG_TMGEN, 0x12); | ||
373 | /* set 1 clock per pixel */ | ||
374 | /* and positive edge clocked pulse high when pixel counter = 0 */ | ||
375 | reg_w(gspca_dev, STK1135_REG_TCP1 + 0, 0x41); | ||
376 | reg_w(gspca_dev, STK1135_REG_TCP1 + 1, 0x00); | ||
377 | reg_w(gspca_dev, STK1135_REG_TCP1 + 2, 0x00); | ||
378 | reg_w(gspca_dev, STK1135_REG_TCP1 + 3, 0x00); | ||
379 | |||
380 | /* enable CLKOUT for sensor */ | ||
381 | reg_w(gspca_dev, STK1135_REG_SENSO + 0, 0x10); | ||
382 | /* disable STOP clock */ | ||
383 | reg_w(gspca_dev, STK1135_REG_SENSO + 1, 0x00); | ||
384 | /* set lower 8 bits of PLL feedback divider */ | ||
385 | reg_w(gspca_dev, STK1135_REG_SENSO + 3, 0x07); | ||
386 | /* set other PLL parameters */ | ||
387 | reg_w(gspca_dev, STK1135_REG_PLLFD, 0x06); | ||
388 | /* enable timing generator */ | ||
389 | reg_w(gspca_dev, STK1135_REG_TMGEN, 0x80); | ||
390 | /* enable PLL */ | ||
391 | reg_w(gspca_dev, STK1135_REG_SENSO + 2, 0x04); | ||
392 | |||
393 | /* set serial interface clock divider (30MHz/0x1f*16+2) = 60240 kHz) */ | ||
394 | reg_w(gspca_dev, STK1135_REG_SICTL + 2, 0x1f); | ||
395 | } | ||
396 | |||
397 | static void stk1135_camera_disable(struct gspca_dev *gspca_dev) | ||
398 | { | ||
399 | /* set capture end Y position to 0 */ | ||
400 | reg_w(gspca_dev, STK1135_REG_CIEPO + 2, 0x00); | ||
401 | reg_w(gspca_dev, STK1135_REG_CIEPO + 3, 0x00); | ||
402 | /* disable capture */ | ||
403 | reg_w_mask(gspca_dev, STK1135_REG_SCTRL, 0x00, 0x80); | ||
404 | |||
405 | /* enable sensor standby and diasble chip enable */ | ||
406 | sensor_write_mask(gspca_dev, 0x00d, 0x0004, 0x000c); | ||
407 | |||
408 | /* disable PLL */ | ||
409 | reg_w_mask(gspca_dev, STK1135_REG_SENSO + 2, 0x00, 0x01); | ||
410 | /* disable timing generator */ | ||
411 | reg_w(gspca_dev, STK1135_REG_TMGEN, 0x00); | ||
412 | /* enable STOP clock */ | ||
413 | reg_w(gspca_dev, STK1135_REG_SENSO + 1, 0x20); | ||
414 | /* disable CLKOUT for sensor */ | ||
415 | reg_w(gspca_dev, STK1135_REG_SENSO, 0x00); | ||
416 | |||
417 | /* disable sensor (GPIO5) and enable GPIO0,3,6 (?) - sensor standby? */ | ||
418 | reg_w(gspca_dev, STK1135_REG_GCTRL, 0x49); | ||
419 | } | ||
420 | |||
421 | /* this function is called at probe and resume time */ | ||
422 | static int sd_init(struct gspca_dev *gspca_dev) | ||
423 | { | ||
424 | u16 sensor_id; | ||
425 | char *sensor_name; | ||
426 | struct sd *sd = (struct sd *) gspca_dev; | ||
427 | |||
428 | /* set GPIO3,4,5,6 direction to output */ | ||
429 | reg_w(gspca_dev, STK1135_REG_GCTRL + 2, 0x78); | ||
430 | /* enable sensor (GPIO5) */ | ||
431 | reg_w(gspca_dev, STK1135_REG_GCTRL, (1 << 5)); | ||
432 | /* disable ROM interface */ | ||
433 | reg_w(gspca_dev, STK1135_REG_GCTRL + 3, 0x80); | ||
434 | /* enable interrupts from GPIO8 (flip sensor) and GPIO9 (???) */ | ||
435 | reg_w(gspca_dev, STK1135_REG_ICTRL + 1, 0x00); | ||
436 | reg_w(gspca_dev, STK1135_REG_ICTRL + 3, 0x03); | ||
437 | /* enable remote wakeup from GPIO9 (???) */ | ||
438 | reg_w(gspca_dev, STK1135_REG_RMCTL + 1, 0x00); | ||
439 | reg_w(gspca_dev, STK1135_REG_RMCTL + 3, 0x02); | ||
440 | |||
441 | /* reset serial interface */ | ||
442 | reg_w(gspca_dev, STK1135_REG_SICTL, 0x80); | ||
443 | reg_w(gspca_dev, STK1135_REG_SICTL, 0x00); | ||
444 | /* set sensor address */ | ||
445 | reg_w(gspca_dev, STK1135_REG_SICTL + 3, 0xba); | ||
446 | /* disable alt 2-wire serial interface */ | ||
447 | reg_w(gspca_dev, STK1135_REG_ASIC + 3, 0x00); | ||
448 | |||
449 | stk1135_configure_clock(gspca_dev); | ||
450 | |||
451 | /* read sensor ID */ | ||
452 | sd->sensor_page = 0xff; | ||
453 | sensor_id = sensor_read(gspca_dev, 0x000); | ||
454 | |||
455 | switch (sensor_id) { | ||
456 | case 0x148c: | ||
457 | sensor_name = "MT9M112"; | ||
458 | break; | ||
459 | default: | ||
460 | sensor_name = "unknown"; | ||
461 | } | ||
462 | pr_info("Detected sensor type %s (0x%x)\n", sensor_name, sensor_id); | ||
463 | |||
464 | stk1135_camera_disable(gspca_dev); | ||
465 | |||
466 | return gspca_dev->usb_err; | ||
467 | } | ||
468 | |||
469 | /* -- start the camera -- */ | ||
470 | static int sd_start(struct gspca_dev *gspca_dev) | ||
471 | { | ||
472 | struct sd *sd = (struct sd *) gspca_dev; | ||
473 | u16 width, height; | ||
474 | |||
475 | /* enable sensor (GPIO5) */ | ||
476 | reg_w(gspca_dev, STK1135_REG_GCTRL, (1 << 5)); | ||
477 | |||
478 | stk1135_configure_clock(gspca_dev); | ||
479 | |||
480 | /* set capture start position X = 0, Y = 0 */ | ||
481 | reg_w(gspca_dev, STK1135_REG_CISPO + 0, 0x00); | ||
482 | reg_w(gspca_dev, STK1135_REG_CISPO + 1, 0x00); | ||
483 | reg_w(gspca_dev, STK1135_REG_CISPO + 2, 0x00); | ||
484 | reg_w(gspca_dev, STK1135_REG_CISPO + 3, 0x00); | ||
485 | |||
486 | /* set capture end position */ | ||
487 | width = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].width; | ||
488 | height = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].height; | ||
489 | reg_w(gspca_dev, STK1135_REG_CIEPO + 0, width & 0xff); | ||
490 | reg_w(gspca_dev, STK1135_REG_CIEPO + 1, width >> 8); | ||
491 | reg_w(gspca_dev, STK1135_REG_CIEPO + 2, height & 0xff); | ||
492 | reg_w(gspca_dev, STK1135_REG_CIEPO + 3, height >> 8); | ||
493 | |||
494 | /* set 8-bit mode */ | ||
495 | reg_w(gspca_dev, STK1135_REG_SCTRL, 0x20); | ||
496 | |||
497 | stk1135_configure_mt9m112(gspca_dev); | ||
498 | |||
499 | /* enable capture */ | ||
500 | reg_w_mask(gspca_dev, STK1135_REG_SCTRL, 0x80, 0x80); | ||
501 | |||
502 | if (gspca_dev->usb_err >= 0) | ||
503 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", | ||
504 | gspca_dev->alt); | ||
505 | |||
506 | sd->pkt_seq = 0; | ||
507 | |||
508 | return gspca_dev->usb_err; | ||
509 | } | ||
510 | |||
511 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
512 | { | ||
513 | struct usb_device *dev = gspca_dev->dev; | ||
514 | |||
515 | usb_set_interface(dev, gspca_dev->iface, 0); | ||
516 | |||
517 | stk1135_camera_disable(gspca_dev); | ||
518 | |||
519 | PDEBUG(D_STREAM, "camera stopped"); | ||
520 | } | ||
521 | |||
522 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
523 | u8 *data, /* isoc packet */ | ||
524 | int len) /* iso packet length */ | ||
525 | { | ||
526 | struct sd *sd = (struct sd *) gspca_dev; | ||
527 | int skip = sizeof(struct stk1135_pkt_header); | ||
528 | bool flip; | ||
529 | enum gspca_packet_type pkt_type = INTER_PACKET; | ||
530 | struct stk1135_pkt_header *hdr = (void *)data; | ||
531 | u8 seq; | ||
532 | |||
533 | if (len < 4) { | ||
534 | PDEBUG(D_PACK, "received short packet (less than 4 bytes)"); | ||
535 | return; | ||
536 | } | ||
537 | |||
538 | /* GPIO 8 is flip sensor (1 = normal position, 0 = flipped to back) */ | ||
539 | flip = !(le16_to_cpu(hdr->gpio) & (1 << 8)); | ||
540 | /* it's a switch, needs software debounce */ | ||
541 | if (sd->flip_status != flip) | ||
542 | sd->flip_debounce++; | ||
543 | else | ||
544 | sd->flip_debounce = 0; | ||
545 | |||
546 | /* check sequence number (not present in new frame packets) */ | ||
547 | if (!(hdr->flags & STK1135_HDR_FRAME_START)) { | ||
548 | seq = hdr->seq & STK1135_HDR_SEQ_MASK; | ||
549 | if (seq != sd->pkt_seq) { | ||
550 | PDEBUG(D_PACK, "received out-of-sequence packet"); | ||
551 | /* resync sequence and discard packet */ | ||
552 | sd->pkt_seq = seq; | ||
553 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
554 | return; | ||
555 | } | ||
556 | } | ||
557 | sd->pkt_seq++; | ||
558 | if (sd->pkt_seq > STK1135_HDR_SEQ_MASK) | ||
559 | sd->pkt_seq = 0; | ||
560 | |||
561 | if (len == sizeof(struct stk1135_pkt_header)) | ||
562 | return; | ||
563 | |||
564 | if (hdr->flags & STK1135_HDR_FRAME_START) { /* new frame */ | ||
565 | skip = 8; /* the header is longer */ | ||
566 | gspca_frame_add(gspca_dev, LAST_PACKET, data, 0); | ||
567 | pkt_type = FIRST_PACKET; | ||
568 | } | ||
569 | gspca_frame_add(gspca_dev, pkt_type, data + skip, len - skip); | ||
570 | } | ||
571 | |||
572 | static void sethflip(struct gspca_dev *gspca_dev, s32 val) | ||
573 | { | ||
574 | struct sd *sd = (struct sd *) gspca_dev; | ||
575 | |||
576 | if (sd->flip_status) | ||
577 | val = !val; | ||
578 | sensor_write_mask(gspca_dev, 0x020, val ? 0x0002 : 0x0000 , 0x0002); | ||
579 | } | ||
580 | |||
581 | static void setvflip(struct gspca_dev *gspca_dev, s32 val) | ||
582 | { | ||
583 | struct sd *sd = (struct sd *) gspca_dev; | ||
584 | |||
585 | if (sd->flip_status) | ||
586 | val = !val; | ||
587 | sensor_write_mask(gspca_dev, 0x020, val ? 0x0001 : 0x0000 , 0x0001); | ||
588 | } | ||
589 | |||
590 | static void stk1135_dq_callback(struct gspca_dev *gspca_dev) | ||
591 | { | ||
592 | struct sd *sd = (struct sd *) gspca_dev; | ||
593 | |||
594 | if (sd->flip_debounce > 100) { | ||
595 | sd->flip_status = !sd->flip_status; | ||
596 | sethflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip)); | ||
597 | setvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->vflip)); | ||
598 | } | ||
599 | } | ||
600 | |||
601 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) | ||
602 | { | ||
603 | struct gspca_dev *gspca_dev = | ||
604 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); | ||
605 | |||
606 | gspca_dev->usb_err = 0; | ||
607 | |||
608 | if (!gspca_dev->streaming) | ||
609 | return 0; | ||
610 | |||
611 | switch (ctrl->id) { | ||
612 | case V4L2_CID_HFLIP: | ||
613 | sethflip(gspca_dev, ctrl->val); | ||
614 | break; | ||
615 | case V4L2_CID_VFLIP: | ||
616 | setvflip(gspca_dev, ctrl->val); | ||
617 | break; | ||
618 | } | ||
619 | |||
620 | return gspca_dev->usb_err; | ||
621 | } | ||
622 | |||
623 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { | ||
624 | .s_ctrl = sd_s_ctrl, | ||
625 | }; | ||
626 | |||
627 | static int sd_init_controls(struct gspca_dev *gspca_dev) | ||
628 | { | ||
629 | struct sd *sd = (struct sd *) gspca_dev; | ||
630 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; | ||
631 | |||
632 | gspca_dev->vdev.ctrl_handler = hdl; | ||
633 | v4l2_ctrl_handler_init(hdl, 2); | ||
634 | sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
635 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
636 | sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
637 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
638 | |||
639 | if (hdl->error) { | ||
640 | pr_err("Could not initialize controls\n"); | ||
641 | return hdl->error; | ||
642 | } | ||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | /* sub-driver description */ | ||
647 | static const struct sd_desc sd_desc = { | ||
648 | .name = MODULE_NAME, | ||
649 | .config = sd_config, | ||
650 | .init = sd_init, | ||
651 | .init_controls = sd_init_controls, | ||
652 | .start = sd_start, | ||
653 | .stopN = sd_stopN, | ||
654 | .pkt_scan = sd_pkt_scan, | ||
655 | .dq_callback = stk1135_dq_callback, | ||
656 | }; | ||
657 | |||
658 | /* -- module initialisation -- */ | ||
659 | static const struct usb_device_id device_table[] = { | ||
660 | {USB_DEVICE(0x174f, 0x6a31)}, /* ASUS laptop, MT9M112 sensor */ | ||
661 | {} | ||
662 | }; | ||
663 | MODULE_DEVICE_TABLE(usb, device_table); | ||
664 | |||
665 | /* -- device connect -- */ | ||
666 | static int sd_probe(struct usb_interface *intf, | ||
667 | const struct usb_device_id *id) | ||
668 | { | ||
669 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
670 | THIS_MODULE); | ||
671 | } | ||
672 | |||
673 | static struct usb_driver sd_driver = { | ||
674 | .name = MODULE_NAME, | ||
675 | .id_table = device_table, | ||
676 | .probe = sd_probe, | ||
677 | .disconnect = gspca_disconnect, | ||
678 | #ifdef CONFIG_PM | ||
679 | .suspend = gspca_suspend, | ||
680 | .resume = gspca_resume, | ||
681 | .reset_resume = gspca_resume, | ||
682 | #endif | ||
683 | }; | ||
684 | |||
685 | module_usb_driver(sd_driver); | ||
diff --git a/drivers/media/usb/gspca/stk1135.h b/drivers/media/usb/gspca/stk1135.h new file mode 100644 index 000000000000..e1dd92ab49bb --- /dev/null +++ b/drivers/media/usb/gspca/stk1135.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * STK1135 registers | ||
3 | * | ||
4 | * Copyright (c) 2013 Ondrej Zary | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define STK1135_REG_GCTRL 0x000 /* GPIO control */ | ||
22 | #define STK1135_REG_ICTRL 0x004 /* Interrupt control */ | ||
23 | #define STK1135_REG_IDATA 0x008 /* Interrupt data */ | ||
24 | #define STK1135_REG_RMCTL 0x00c /* Remote wakeup control */ | ||
25 | #define STK1135_REG_POSVA 0x010 /* Power-on strapping data */ | ||
26 | |||
27 | #define STK1135_REG_SENSO 0x018 /* Sensor select options */ | ||
28 | #define STK1135_REG_PLLFD 0x01c /* PLL frequency divider */ | ||
29 | |||
30 | #define STK1135_REG_SCTRL 0x100 /* Sensor control register */ | ||
31 | #define STK1135_REG_DCTRL 0x104 /* Decimation control register */ | ||
32 | #define STK1135_REG_CISPO 0x110 /* Capture image starting position */ | ||
33 | #define STK1135_REG_CIEPO 0x114 /* Capture image ending position */ | ||
34 | #define STK1135_REG_TCTRL 0x120 /* Test data control */ | ||
35 | |||
36 | #define STK1135_REG_SICTL 0x200 /* Serial interface control register */ | ||
37 | #define STK1135_REG_SBUSW 0x204 /* Serial bus write */ | ||
38 | #define STK1135_REG_SBUSR 0x208 /* Serial bus read */ | ||
39 | #define STK1135_REG_SCSI 0x20c /* Software control serial interface */ | ||
40 | #define STK1135_REG_GSBWP 0x210 /* General serial bus write port */ | ||
41 | #define STK1135_REG_GSBRP 0x214 /* General serial bus read port */ | ||
42 | #define STK1135_REG_ASIC 0x2fc /* Alternate serial interface control */ | ||
43 | |||
44 | #define STK1135_REG_TMGEN 0x300 /* Timing generator */ | ||
45 | #define STK1135_REG_TCP1 0x350 /* Timing control parameter 1 */ | ||
46 | |||
47 | struct stk1135_pkt_header { | ||
48 | u8 flags; | ||
49 | u8 seq; | ||
50 | __le16 gpio; | ||
51 | } __packed; | ||
52 | |||
53 | #define STK1135_HDR_FRAME_START (1 << 7) | ||
54 | #define STK1135_HDR_ODD (1 << 6) | ||
55 | #define STK1135_HDR_I2C_VBLANK (1 << 5) | ||
56 | |||
57 | #define STK1135_HDR_SEQ_MASK 0x3f | ||
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 4f8567aa99d8..0500c4175d5f 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/v4l2-dv-timings.h> | 24 | #include <linux/v4l2-dv-timings.h> |
25 | #include <media/v4l2-dev.h> | 25 | #include <media/v4l2-dev.h> |
26 | #include <media/v4l2-common.h> | 26 | #include <media/v4l2-common.h> |
27 | #include <media/v4l2-dv-timings.h> | ||
27 | #include <media/v4l2-ioctl.h> | 28 | #include <media/v4l2-ioctl.h> |
28 | #include <media/v4l2-event.h> | 29 | #include <media/v4l2-event.h> |
29 | #include "hdpvr.h" | 30 | #include "hdpvr.h" |
@@ -641,7 +642,7 @@ static int vidioc_s_dv_timings(struct file *file, void *_fh, | |||
641 | if (dev->status != STATUS_IDLE) | 642 | if (dev->status != STATUS_IDLE) |
642 | return -EBUSY; | 643 | return -EBUSY; |
643 | for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) | 644 | for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) |
644 | if (v4l_match_dv_timings(timings, hdpvr_dv_timings + i, 0)) | 645 | if (v4l2_match_dv_timings(timings, hdpvr_dv_timings + i, 0)) |
645 | break; | 646 | break; |
646 | if (i == ARRAY_SIZE(hdpvr_dv_timings)) | 647 | if (i == ARRAY_SIZE(hdpvr_dv_timings)) |
647 | return -EINVAL; | 648 | return -EINVAL; |
@@ -689,10 +690,8 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, | |||
689 | unsigned vsize; | 690 | unsigned vsize; |
690 | unsigned fps; | 691 | unsigned fps; |
691 | 692 | ||
692 | hsize = bt->hfrontporch + bt->hsync + bt->hbackporch + bt->width; | 693 | hsize = V4L2_DV_BT_FRAME_WIDTH(bt); |
693 | vsize = bt->vfrontporch + bt->vsync + bt->vbackporch + | 694 | vsize = V4L2_DV_BT_FRAME_HEIGHT(bt); |
694 | bt->il_vfrontporch + bt->il_vsync + bt->il_vbackporch + | ||
695 | bt->height; | ||
696 | fps = (unsigned)bt->pixelclock / (hsize * vsize); | 695 | fps = (unsigned)bt->pixelclock / (hsize * vsize); |
697 | if (bt->width != vid_info.width || | 696 | if (bt->width != vid_info.width || |
698 | bt->height != vid_info.height || | 697 | bt->height != vid_info.height || |
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index ab97e7d0b4f2..6bc9b8e19e20 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * s2255drv.c - a driver for the Sensoray 2255 USB video capture device | 2 | * s2255drv.c - a driver for the Sensoray 2255 USB video capture device |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2010 by Sensoray Company Inc. | 4 | * Copyright (C) 2007-2013 by Sensoray Company Inc. |
5 | * Dean Anderson | 5 | * Dean Anderson |
6 | * | 6 | * |
7 | * Some video buffer code based on vivi driver: | 7 | * Some video buffer code based on vivi driver: |
@@ -52,7 +52,7 @@ | |||
52 | #include <media/v4l2-ctrls.h> | 52 | #include <media/v4l2-ctrls.h> |
53 | #include <media/v4l2-event.h> | 53 | #include <media/v4l2-event.h> |
54 | 54 | ||
55 | #define S2255_VERSION "1.22.1" | 55 | #define S2255_VERSION "1.23.1" |
56 | #define FIRMWARE_FILE_NAME "f2255usb.bin" | 56 | #define FIRMWARE_FILE_NAME "f2255usb.bin" |
57 | 57 | ||
58 | /* default JPEG quality */ | 58 | /* default JPEG quality */ |
@@ -1303,11 +1303,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id i) | |||
1303 | int ret = 0; | 1303 | int ret = 0; |
1304 | 1304 | ||
1305 | mutex_lock(&q->vb_lock); | 1305 | mutex_lock(&q->vb_lock); |
1306 | if (videobuf_queue_is_busy(q)) { | ||
1307 | dprintk(1, "queue busy\n"); | ||
1308 | ret = -EBUSY; | ||
1309 | goto out_s_std; | ||
1310 | } | ||
1311 | if (res_locked(fh)) { | 1306 | if (res_locked(fh)) { |
1312 | dprintk(1, "can't change standard after started\n"); | 1307 | dprintk(1, "can't change standard after started\n"); |
1313 | ret = -EBUSY; | 1308 | ret = -EBUSY; |
diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig index 1c3a1ec00237..95584c15dc5a 100644 --- a/drivers/media/usb/stk1160/Kconfig +++ b/drivers/media/usb/stk1160/Kconfig | |||
@@ -1,8 +1,6 @@ | |||
1 | config VIDEO_STK1160 | 1 | config VIDEO_STK1160_COMMON |
2 | tristate "STK1160 USB video capture support" | 2 | tristate "STK1160 USB video capture support" |
3 | depends on VIDEO_DEV && I2C | 3 | depends on VIDEO_DEV && I2C |
4 | select VIDEOBUF2_VMALLOC | ||
5 | select VIDEO_SAA711X | ||
6 | 4 | ||
7 | ---help--- | 5 | ---help--- |
8 | This is a video4linux driver for STK1160 based video capture devices. | 6 | This is a video4linux driver for STK1160 based video capture devices. |
@@ -12,9 +10,15 @@ config VIDEO_STK1160 | |||
12 | 10 | ||
13 | config VIDEO_STK1160_AC97 | 11 | config VIDEO_STK1160_AC97 |
14 | bool "STK1160 AC97 codec support" | 12 | bool "STK1160 AC97 codec support" |
15 | depends on VIDEO_STK1160 && SND | 13 | depends on VIDEO_STK1160_COMMON && SND |
16 | select SND_AC97_CODEC | ||
17 | 14 | ||
18 | ---help--- | 15 | ---help--- |
19 | Enables AC97 codec support for stk1160 driver. | 16 | Enables AC97 codec support for stk1160 driver. |
20 | . | 17 | |
18 | config VIDEO_STK1160 | ||
19 | tristate | ||
20 | depends on (!VIDEO_STK1160_AC97 || (SND='n') || SND) && VIDEO_STK1160_COMMON | ||
21 | default y | ||
22 | select VIDEOBUF2_VMALLOC | ||
23 | select VIDEO_SAA711X | ||
24 | select SND_AC97_CODEC if SND | ||
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index 876fc26565e3..c45c9881bb5f 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c | |||
@@ -379,6 +379,9 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) | |||
379 | struct stk1160 *dev = video_drvdata(file); | 379 | struct stk1160 *dev = video_drvdata(file); |
380 | struct vb2_queue *q = &dev->vb_vidq; | 380 | struct vb2_queue *q = &dev->vb_vidq; |
381 | 381 | ||
382 | if (dev->norm == norm) | ||
383 | return 0; | ||
384 | |||
382 | if (vb2_is_busy(q)) | 385 | if (vb2_is_busy(q)) |
383 | return -EBUSY; | 386 | return -EBUSY; |
384 | 387 | ||
@@ -440,9 +443,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
440 | { | 443 | { |
441 | struct stk1160 *dev = video_drvdata(file); | 444 | struct stk1160 *dev = video_drvdata(file); |
442 | 445 | ||
443 | if (vb2_is_busy(&dev->vb_vidq)) | ||
444 | return -EBUSY; | ||
445 | |||
446 | if (i > STK1160_MAX_INPUT) | 446 | if (i > STK1160_MAX_INPUT) |
447 | return -EINVAL; | 447 | return -EINVAL; |
448 | 448 | ||
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c index e07e4c699cc2..95f94e5aa66d 100644 --- a/drivers/media/usb/tlg2300/pd-main.c +++ b/drivers/media/usb/tlg2300/pd-main.c | |||
@@ -375,7 +375,7 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) | |||
375 | } | 375 | } |
376 | #endif | 376 | #endif |
377 | 377 | ||
378 | static int check_firmware(struct usb_device *udev, int *down_firmware) | 378 | static int check_firmware(struct usb_device *udev) |
379 | { | 379 | { |
380 | void *buf; | 380 | void *buf; |
381 | int ret; | 381 | int ret; |
@@ -395,10 +395,8 @@ static int check_firmware(struct usb_device *udev, int *down_firmware) | |||
395 | USB_CTRL_GET_TIMEOUT); | 395 | USB_CTRL_GET_TIMEOUT); |
396 | kfree(buf); | 396 | kfree(buf); |
397 | 397 | ||
398 | if (ret < 0) { | 398 | if (ret < 0) |
399 | *down_firmware = 1; | ||
400 | return firmware_download(udev); | 399 | return firmware_download(udev); |
401 | } | ||
402 | return 0; | 400 | return 0; |
403 | } | 401 | } |
404 | 402 | ||
@@ -411,9 +409,9 @@ static int poseidon_probe(struct usb_interface *interface, | |||
411 | int new_one = 0; | 409 | int new_one = 0; |
412 | 410 | ||
413 | /* download firmware */ | 411 | /* download firmware */ |
414 | check_firmware(udev, &ret); | 412 | ret = check_firmware(udev); |
415 | if (ret) | 413 | if (ret) |
416 | return 0; | 414 | return ret; |
417 | 415 | ||
418 | /* Do I recovery from the hibernate ? */ | 416 | /* Do I recovery from the hibernate ? */ |
419 | pd = find_old_poseidon(udev); | 417 | pd = find_old_poseidon(udev); |
@@ -436,12 +434,22 @@ static int poseidon_probe(struct usb_interface *interface, | |||
436 | 434 | ||
437 | /* register v4l2 device */ | 435 | /* register v4l2 device */ |
438 | ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev); | 436 | ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev); |
437 | if (ret) | ||
438 | goto err_v4l2; | ||
439 | 439 | ||
440 | /* register devices in directory /dev */ | 440 | /* register devices in directory /dev */ |
441 | ret = pd_video_init(pd); | 441 | ret = pd_video_init(pd); |
442 | poseidon_audio_init(pd); | 442 | if (ret) |
443 | poseidon_fm_init(pd); | 443 | goto err_video; |
444 | pd_dvb_usb_device_init(pd); | 444 | ret = poseidon_audio_init(pd); |
445 | if (ret) | ||
446 | goto err_audio; | ||
447 | ret = poseidon_fm_init(pd); | ||
448 | if (ret) | ||
449 | goto err_fm; | ||
450 | ret = pd_dvb_usb_device_init(pd); | ||
451 | if (ret) | ||
452 | goto err_dvb; | ||
445 | 453 | ||
446 | INIT_LIST_HEAD(&pd->device_list); | 454 | INIT_LIST_HEAD(&pd->device_list); |
447 | list_add_tail(&pd->device_list, &pd_device_list); | 455 | list_add_tail(&pd->device_list, &pd_device_list); |
@@ -459,6 +467,17 @@ static int poseidon_probe(struct usb_interface *interface, | |||
459 | } | 467 | } |
460 | #endif | 468 | #endif |
461 | return 0; | 469 | return 0; |
470 | err_dvb: | ||
471 | poseidon_fm_exit(pd); | ||
472 | err_fm: | ||
473 | poseidon_audio_free(pd); | ||
474 | err_audio: | ||
475 | pd_video_exit(pd); | ||
476 | err_video: | ||
477 | v4l2_device_unregister(&pd->v4l2_dev); | ||
478 | err_v4l2: | ||
479 | kfree(pd); | ||
480 | return ret; | ||
462 | } | 481 | } |
463 | 482 | ||
464 | static void poseidon_disconnect(struct usb_interface *interface) | 483 | static void poseidon_disconnect(struct usb_interface *interface) |
diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index 91650173941a..8a505a90d318 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/usb.h> | 35 | #include <linux/usb.h> |
36 | #include <linux/version.h> | ||
37 | #include <linux/videodev2.h> | 36 | #include <linux/videodev2.h> |
38 | 37 | ||
39 | #include <media/v4l2-device.h> | 38 | #include <media/v4l2-device.h> |
@@ -91,17 +90,78 @@ struct usbtv { | |||
91 | u32 frame_id; | 90 | u32 frame_id; |
92 | int chunks_done; | 91 | int chunks_done; |
93 | 92 | ||
93 | enum { | ||
94 | USBTV_COMPOSITE_INPUT, | ||
95 | USBTV_SVIDEO_INPUT, | ||
96 | } input; | ||
94 | int iso_size; | 97 | int iso_size; |
95 | unsigned int sequence; | 98 | unsigned int sequence; |
96 | struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; | 99 | struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; |
97 | }; | 100 | }; |
98 | 101 | ||
99 | static int usbtv_setup_capture(struct usbtv *usbtv) | 102 | static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size) |
100 | { | 103 | { |
101 | int ret; | 104 | int ret; |
102 | int pipe = usb_rcvctrlpipe(usbtv->udev, 0); | 105 | int pipe = usb_rcvctrlpipe(usbtv->udev, 0); |
103 | int i; | 106 | int i; |
104 | static const u16 protoregs[][2] = { | 107 | |
108 | for (i = 0; i < size; i++) { | ||
109 | u16 index = regs[i][0]; | ||
110 | u16 value = regs[i][1]; | ||
111 | |||
112 | ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, | ||
113 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
114 | value, index, NULL, 0, 0); | ||
115 | if (ret < 0) | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int usbtv_select_input(struct usbtv *usbtv, int input) | ||
123 | { | ||
124 | int ret; | ||
125 | |||
126 | static const u16 composite[][2] = { | ||
127 | { USBTV_BASE + 0x0105, 0x0060 }, | ||
128 | { USBTV_BASE + 0x011f, 0x00f2 }, | ||
129 | { USBTV_BASE + 0x0127, 0x0060 }, | ||
130 | { USBTV_BASE + 0x00ae, 0x0010 }, | ||
131 | { USBTV_BASE + 0x0284, 0x00aa }, | ||
132 | { USBTV_BASE + 0x0239, 0x0060 }, | ||
133 | }; | ||
134 | |||
135 | static const u16 svideo[][2] = { | ||
136 | { USBTV_BASE + 0x0105, 0x0010 }, | ||
137 | { USBTV_BASE + 0x011f, 0x00ff }, | ||
138 | { USBTV_BASE + 0x0127, 0x0060 }, | ||
139 | { USBTV_BASE + 0x00ae, 0x0030 }, | ||
140 | { USBTV_BASE + 0x0284, 0x0088 }, | ||
141 | { USBTV_BASE + 0x0239, 0x0060 }, | ||
142 | }; | ||
143 | |||
144 | switch (input) { | ||
145 | case USBTV_COMPOSITE_INPUT: | ||
146 | ret = usbtv_set_regs(usbtv, composite, ARRAY_SIZE(composite)); | ||
147 | break; | ||
148 | case USBTV_SVIDEO_INPUT: | ||
149 | ret = usbtv_set_regs(usbtv, svideo, ARRAY_SIZE(svideo)); | ||
150 | break; | ||
151 | default: | ||
152 | ret = -EINVAL; | ||
153 | } | ||
154 | |||
155 | if (!ret) | ||
156 | usbtv->input = input; | ||
157 | |||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | static int usbtv_setup_capture(struct usbtv *usbtv) | ||
162 | { | ||
163 | int ret; | ||
164 | static const u16 setup[][2] = { | ||
105 | /* These seem to enable the device. */ | 165 | /* These seem to enable the device. */ |
106 | { USBTV_BASE + 0x0008, 0x0001 }, | 166 | { USBTV_BASE + 0x0008, 0x0001 }, |
107 | { USBTV_BASE + 0x01d0, 0x00ff }, | 167 | { USBTV_BASE + 0x01d0, 0x00ff }, |
@@ -189,16 +249,13 @@ static int usbtv_setup_capture(struct usbtv *usbtv) | |||
189 | { USBTV_BASE + 0x024f, 0x0002 }, | 249 | { USBTV_BASE + 0x024f, 0x0002 }, |
190 | }; | 250 | }; |
191 | 251 | ||
192 | for (i = 0; i < ARRAY_SIZE(protoregs); i++) { | 252 | ret = usbtv_set_regs(usbtv, setup, ARRAY_SIZE(setup)); |
193 | u16 index = protoregs[i][0]; | 253 | if (ret) |
194 | u16 value = protoregs[i][1]; | 254 | return ret; |
195 | 255 | ||
196 | ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, | 256 | ret = usbtv_select_input(usbtv, usbtv->input); |
197 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 257 | if (ret) |
198 | value, index, NULL, 0, 0); | 258 | return ret; |
199 | if (ret < 0) | ||
200 | return ret; | ||
201 | } | ||
202 | 259 | ||
203 | return 0; | 260 | return 0; |
204 | } | 261 | } |
@@ -443,10 +500,17 @@ static int usbtv_querycap(struct file *file, void *priv, | |||
443 | static int usbtv_enum_input(struct file *file, void *priv, | 500 | static int usbtv_enum_input(struct file *file, void *priv, |
444 | struct v4l2_input *i) | 501 | struct v4l2_input *i) |
445 | { | 502 | { |
446 | if (i->index > 0) | 503 | switch (i->index) { |
504 | case USBTV_COMPOSITE_INPUT: | ||
505 | strlcpy(i->name, "Composite", sizeof(i->name)); | ||
506 | break; | ||
507 | case USBTV_SVIDEO_INPUT: | ||
508 | strlcpy(i->name, "S-Video", sizeof(i->name)); | ||
509 | break; | ||
510 | default: | ||
447 | return -EINVAL; | 511 | return -EINVAL; |
512 | } | ||
448 | 513 | ||
449 | strlcpy(i->name, "Composite", sizeof(i->name)); | ||
450 | i->type = V4L2_INPUT_TYPE_CAMERA; | 514 | i->type = V4L2_INPUT_TYPE_CAMERA; |
451 | i->std = V4L2_STD_525_60; | 515 | i->std = V4L2_STD_525_60; |
452 | return 0; | 516 | return 0; |
@@ -486,15 +550,15 @@ static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm) | |||
486 | 550 | ||
487 | static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) | 551 | static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) |
488 | { | 552 | { |
489 | *i = 0; | 553 | struct usbtv *usbtv = video_drvdata(file); |
554 | *i = usbtv->input; | ||
490 | return 0; | 555 | return 0; |
491 | } | 556 | } |
492 | 557 | ||
493 | static int usbtv_s_input(struct file *file, void *priv, unsigned int i) | 558 | static int usbtv_s_input(struct file *file, void *priv, unsigned int i) |
494 | { | 559 | { |
495 | if (i > 0) | 560 | struct usbtv *usbtv = video_drvdata(file); |
496 | return -EINVAL; | 561 | return usbtv_select_input(usbtv, i); |
497 | return 0; | ||
498 | } | 562 | } |
499 | 563 | ||
500 | static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) | 564 | static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) |
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 4c33b8d6520c..1a85eee581f8 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile | |||
@@ -17,6 +17,7 @@ endif | |||
17 | obj-$(CONFIG_VIDEO_V4L2) += videodev.o | 17 | obj-$(CONFIG_VIDEO_V4L2) += videodev.o |
18 | obj-$(CONFIG_VIDEO_V4L2_INT_DEVICE) += v4l2-int-device.o | 18 | obj-$(CONFIG_VIDEO_V4L2_INT_DEVICE) += v4l2-int-device.o |
19 | obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o | 19 | obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o |
20 | obj-$(CONFIG_VIDEO_V4L2) += v4l2-dv-timings.o | ||
20 | 21 | ||
21 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o | 22 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o |
22 | 23 | ||
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index aae241730caa..c85d69da35bd 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c | |||
@@ -27,7 +27,6 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) | |||
27 | #if IS_ENABLED(CONFIG_I2C) | 27 | #if IS_ENABLED(CONFIG_I2C) |
28 | struct i2c_client *client = i2c_verify_client(dev); | 28 | struct i2c_client *client = i2c_verify_client(dev); |
29 | return client && | 29 | return client && |
30 | asd->bus_type == V4L2_ASYNC_BUS_I2C && | ||
31 | asd->match.i2c.adapter_id == client->adapter->nr && | 30 | asd->match.i2c.adapter_id == client->adapter->nr && |
32 | asd->match.i2c.address == client->addr; | 31 | asd->match.i2c.address == client->addr; |
33 | #else | 32 | #else |
@@ -35,10 +34,14 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) | |||
35 | #endif | 34 | #endif |
36 | } | 35 | } |
37 | 36 | ||
38 | static bool match_platform(struct device *dev, struct v4l2_async_subdev *asd) | 37 | static bool match_devname(struct device *dev, struct v4l2_async_subdev *asd) |
39 | { | 38 | { |
40 | return asd->bus_type == V4L2_ASYNC_BUS_PLATFORM && | 39 | return !strcmp(asd->match.device_name.name, dev_name(dev)); |
41 | !strcmp(asd->match.platform.name, dev_name(dev)); | 40 | } |
41 | |||
42 | static bool match_of(struct device *dev, struct v4l2_async_subdev *asd) | ||
43 | { | ||
44 | return dev->of_node == asd->match.of.node; | ||
42 | } | 45 | } |
43 | 46 | ||
44 | static LIST_HEAD(subdev_list); | 47 | static LIST_HEAD(subdev_list); |
@@ -46,28 +49,29 @@ static LIST_HEAD(notifier_list); | |||
46 | static DEFINE_MUTEX(list_lock); | 49 | static DEFINE_MUTEX(list_lock); |
47 | 50 | ||
48 | static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, | 51 | static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, |
49 | struct v4l2_async_subdev_list *asdl) | 52 | struct v4l2_subdev *sd) |
50 | { | 53 | { |
51 | struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); | ||
52 | struct v4l2_async_subdev *asd; | 54 | struct v4l2_async_subdev *asd; |
53 | bool (*match)(struct device *, | 55 | bool (*match)(struct device *, struct v4l2_async_subdev *); |
54 | struct v4l2_async_subdev *); | ||
55 | 56 | ||
56 | list_for_each_entry(asd, ¬ifier->waiting, list) { | 57 | list_for_each_entry(asd, ¬ifier->waiting, list) { |
57 | /* bus_type has been verified valid before */ | 58 | /* bus_type has been verified valid before */ |
58 | switch (asd->bus_type) { | 59 | switch (asd->match_type) { |
59 | case V4L2_ASYNC_BUS_CUSTOM: | 60 | case V4L2_ASYNC_MATCH_CUSTOM: |
60 | match = asd->match.custom.match; | 61 | match = asd->match.custom.match; |
61 | if (!match) | 62 | if (!match) |
62 | /* Match always */ | 63 | /* Match always */ |
63 | return asd; | 64 | return asd; |
64 | break; | 65 | break; |
65 | case V4L2_ASYNC_BUS_PLATFORM: | 66 | case V4L2_ASYNC_MATCH_DEVNAME: |
66 | match = match_platform; | 67 | match = match_devname; |
67 | break; | 68 | break; |
68 | case V4L2_ASYNC_BUS_I2C: | 69 | case V4L2_ASYNC_MATCH_I2C: |
69 | match = match_i2c; | 70 | match = match_i2c; |
70 | break; | 71 | break; |
72 | case V4L2_ASYNC_MATCH_OF: | ||
73 | match = match_of; | ||
74 | break; | ||
71 | default: | 75 | default: |
72 | /* Cannot happen, unless someone breaks us */ | 76 | /* Cannot happen, unless someone breaks us */ |
73 | WARN_ON(true); | 77 | WARN_ON(true); |
@@ -83,16 +87,15 @@ static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier * | |||
83 | } | 87 | } |
84 | 88 | ||
85 | static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, | 89 | static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, |
86 | struct v4l2_async_subdev_list *asdl, | 90 | struct v4l2_subdev *sd, |
87 | struct v4l2_async_subdev *asd) | 91 | struct v4l2_async_subdev *asd) |
88 | { | 92 | { |
89 | struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); | ||
90 | int ret; | 93 | int ret; |
91 | 94 | ||
92 | /* Remove from the waiting list */ | 95 | /* Remove from the waiting list */ |
93 | list_del(&asd->list); | 96 | list_del(&asd->list); |
94 | asdl->asd = asd; | 97 | sd->asd = asd; |
95 | asdl->notifier = notifier; | 98 | sd->notifier = notifier; |
96 | 99 | ||
97 | if (notifier->bound) { | 100 | if (notifier->bound) { |
98 | ret = notifier->bound(notifier, sd, asd); | 101 | ret = notifier->bound(notifier, sd, asd); |
@@ -100,7 +103,7 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, | |||
100 | return ret; | 103 | return ret; |
101 | } | 104 | } |
102 | /* Move from the global subdevice list to notifier's done */ | 105 | /* Move from the global subdevice list to notifier's done */ |
103 | list_move(&asdl->list, ¬ifier->done); | 106 | list_move(&sd->async_list, ¬ifier->done); |
104 | 107 | ||
105 | ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); | 108 | ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); |
106 | if (ret < 0) { | 109 | if (ret < 0) { |
@@ -115,21 +118,19 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, | |||
115 | return 0; | 118 | return 0; |
116 | } | 119 | } |
117 | 120 | ||
118 | static void v4l2_async_cleanup(struct v4l2_async_subdev_list *asdl) | 121 | static void v4l2_async_cleanup(struct v4l2_subdev *sd) |
119 | { | 122 | { |
120 | struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); | ||
121 | |||
122 | v4l2_device_unregister_subdev(sd); | 123 | v4l2_device_unregister_subdev(sd); |
123 | /* Subdevice driver will reprobe and put asdl back onto the list */ | 124 | /* Subdevice driver will reprobe and put the subdev back onto the list */ |
124 | list_del_init(&asdl->list); | 125 | list_del_init(&sd->async_list); |
125 | asdl->asd = NULL; | 126 | sd->asd = NULL; |
126 | sd->dev = NULL; | 127 | sd->dev = NULL; |
127 | } | 128 | } |
128 | 129 | ||
129 | int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, | 130 | int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, |
130 | struct v4l2_async_notifier *notifier) | 131 | struct v4l2_async_notifier *notifier) |
131 | { | 132 | { |
132 | struct v4l2_async_subdev_list *asdl, *tmp; | 133 | struct v4l2_subdev *sd, *tmp; |
133 | struct v4l2_async_subdev *asd; | 134 | struct v4l2_async_subdev *asd; |
134 | int i; | 135 | int i; |
135 | 136 | ||
@@ -141,17 +142,18 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, | |||
141 | INIT_LIST_HEAD(¬ifier->done); | 142 | INIT_LIST_HEAD(¬ifier->done); |
142 | 143 | ||
143 | for (i = 0; i < notifier->num_subdevs; i++) { | 144 | for (i = 0; i < notifier->num_subdevs; i++) { |
144 | asd = notifier->subdev[i]; | 145 | asd = notifier->subdevs[i]; |
145 | 146 | ||
146 | switch (asd->bus_type) { | 147 | switch (asd->match_type) { |
147 | case V4L2_ASYNC_BUS_CUSTOM: | 148 | case V4L2_ASYNC_MATCH_CUSTOM: |
148 | case V4L2_ASYNC_BUS_PLATFORM: | 149 | case V4L2_ASYNC_MATCH_DEVNAME: |
149 | case V4L2_ASYNC_BUS_I2C: | 150 | case V4L2_ASYNC_MATCH_I2C: |
151 | case V4L2_ASYNC_MATCH_OF: | ||
150 | break; | 152 | break; |
151 | default: | 153 | default: |
152 | dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, | 154 | dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, |
153 | "Invalid bus-type %u on %p\n", | 155 | "Invalid match type %u on %p\n", |
154 | asd->bus_type, asd); | 156 | asd->match_type, asd); |
155 | return -EINVAL; | 157 | return -EINVAL; |
156 | } | 158 | } |
157 | list_add_tail(&asd->list, ¬ifier->waiting); | 159 | list_add_tail(&asd->list, ¬ifier->waiting); |
@@ -162,14 +164,14 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, | |||
162 | /* Keep also completed notifiers on the list */ | 164 | /* Keep also completed notifiers on the list */ |
163 | list_add(¬ifier->list, ¬ifier_list); | 165 | list_add(¬ifier->list, ¬ifier_list); |
164 | 166 | ||
165 | list_for_each_entry_safe(asdl, tmp, &subdev_list, list) { | 167 | list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) { |
166 | int ret; | 168 | int ret; |
167 | 169 | ||
168 | asd = v4l2_async_belongs(notifier, asdl); | 170 | asd = v4l2_async_belongs(notifier, sd); |
169 | if (!asd) | 171 | if (!asd) |
170 | continue; | 172 | continue; |
171 | 173 | ||
172 | ret = v4l2_async_test_notify(notifier, asdl, asd); | 174 | ret = v4l2_async_test_notify(notifier, sd, asd); |
173 | if (ret < 0) { | 175 | if (ret < 0) { |
174 | mutex_unlock(&list_lock); | 176 | mutex_unlock(&list_lock); |
175 | return ret; | 177 | return ret; |
@@ -184,28 +186,29 @@ EXPORT_SYMBOL(v4l2_async_notifier_register); | |||
184 | 186 | ||
185 | void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) | 187 | void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) |
186 | { | 188 | { |
187 | struct v4l2_async_subdev_list *asdl, *tmp; | 189 | struct v4l2_subdev *sd, *tmp; |
188 | unsigned int notif_n_subdev = notifier->num_subdevs; | 190 | unsigned int notif_n_subdev = notifier->num_subdevs; |
189 | unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS); | 191 | unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS); |
190 | struct device *dev[n_subdev]; | 192 | struct device *dev[n_subdev]; |
191 | int i = 0; | 193 | int i = 0; |
192 | 194 | ||
195 | if (!notifier->v4l2_dev) | ||
196 | return; | ||
197 | |||
193 | mutex_lock(&list_lock); | 198 | mutex_lock(&list_lock); |
194 | 199 | ||
195 | list_del(¬ifier->list); | 200 | list_del(¬ifier->list); |
196 | 201 | ||
197 | list_for_each_entry_safe(asdl, tmp, ¬ifier->done, list) { | 202 | list_for_each_entry_safe(sd, tmp, ¬ifier->done, async_list) { |
198 | struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); | ||
199 | |||
200 | dev[i] = get_device(sd->dev); | 203 | dev[i] = get_device(sd->dev); |
201 | 204 | ||
202 | v4l2_async_cleanup(asdl); | 205 | v4l2_async_cleanup(sd); |
203 | 206 | ||
204 | /* If we handled USB devices, we'd have to lock the parent too */ | 207 | /* If we handled USB devices, we'd have to lock the parent too */ |
205 | device_release_driver(dev[i++]); | 208 | device_release_driver(dev[i++]); |
206 | 209 | ||
207 | if (notifier->unbind) | 210 | if (notifier->unbind) |
208 | notifier->unbind(notifier, sd, sd->asdl.asd); | 211 | notifier->unbind(notifier, sd, sd->asd); |
209 | } | 212 | } |
210 | 213 | ||
211 | mutex_unlock(&list_lock); | 214 | mutex_unlock(&list_lock); |
@@ -225,6 +228,9 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) | |||
225 | } | 228 | } |
226 | put_device(d); | 229 | put_device(d); |
227 | } | 230 | } |
231 | |||
232 | notifier->v4l2_dev = NULL; | ||
233 | |||
228 | /* | 234 | /* |
229 | * Don't care about the waiting list, it is initialised and populated | 235 | * Don't care about the waiting list, it is initialised and populated |
230 | * upon notifier registration. | 236 | * upon notifier registration. |
@@ -234,24 +240,23 @@ EXPORT_SYMBOL(v4l2_async_notifier_unregister); | |||
234 | 240 | ||
235 | int v4l2_async_register_subdev(struct v4l2_subdev *sd) | 241 | int v4l2_async_register_subdev(struct v4l2_subdev *sd) |
236 | { | 242 | { |
237 | struct v4l2_async_subdev_list *asdl = &sd->asdl; | ||
238 | struct v4l2_async_notifier *notifier; | 243 | struct v4l2_async_notifier *notifier; |
239 | 244 | ||
240 | mutex_lock(&list_lock); | 245 | mutex_lock(&list_lock); |
241 | 246 | ||
242 | INIT_LIST_HEAD(&asdl->list); | 247 | INIT_LIST_HEAD(&sd->async_list); |
243 | 248 | ||
244 | list_for_each_entry(notifier, ¬ifier_list, list) { | 249 | list_for_each_entry(notifier, ¬ifier_list, list) { |
245 | struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, asdl); | 250 | struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, sd); |
246 | if (asd) { | 251 | if (asd) { |
247 | int ret = v4l2_async_test_notify(notifier, asdl, asd); | 252 | int ret = v4l2_async_test_notify(notifier, sd, asd); |
248 | mutex_unlock(&list_lock); | 253 | mutex_unlock(&list_lock); |
249 | return ret; | 254 | return ret; |
250 | } | 255 | } |
251 | } | 256 | } |
252 | 257 | ||
253 | /* None matched, wait for hot-plugging */ | 258 | /* None matched, wait for hot-plugging */ |
254 | list_add(&asdl->list, &subdev_list); | 259 | list_add(&sd->async_list, &subdev_list); |
255 | 260 | ||
256 | mutex_unlock(&list_lock); | 261 | mutex_unlock(&list_lock); |
257 | 262 | ||
@@ -261,23 +266,22 @@ EXPORT_SYMBOL(v4l2_async_register_subdev); | |||
261 | 266 | ||
262 | void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) | 267 | void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) |
263 | { | 268 | { |
264 | struct v4l2_async_subdev_list *asdl = &sd->asdl; | 269 | struct v4l2_async_notifier *notifier = sd->notifier; |
265 | struct v4l2_async_notifier *notifier = asdl->notifier; | ||
266 | 270 | ||
267 | if (!asdl->asd) { | 271 | if (!sd->asd) { |
268 | if (!list_empty(&asdl->list)) | 272 | if (!list_empty(&sd->async_list)) |
269 | v4l2_async_cleanup(asdl); | 273 | v4l2_async_cleanup(sd); |
270 | return; | 274 | return; |
271 | } | 275 | } |
272 | 276 | ||
273 | mutex_lock(&list_lock); | 277 | mutex_lock(&list_lock); |
274 | 278 | ||
275 | list_add(&asdl->asd->list, ¬ifier->waiting); | 279 | list_add(&sd->asd->list, ¬ifier->waiting); |
276 | 280 | ||
277 | v4l2_async_cleanup(asdl); | 281 | v4l2_async_cleanup(sd); |
278 | 282 | ||
279 | if (notifier->unbind) | 283 | if (notifier->unbind) |
280 | notifier->unbind(notifier, sd, sd->asdl.asd); | 284 | notifier->unbind(notifier, sd, sd->asd); |
281 | 285 | ||
282 | mutex_unlock(&list_lock); | 286 | mutex_unlock(&list_lock); |
283 | } | 287 | } |
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index a95e5e23403f..037d7a55aa8c 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c | |||
@@ -495,363 +495,6 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, | |||
495 | } | 495 | } |
496 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); | 496 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); |
497 | 497 | ||
498 | /** | ||
499 | * v4l_match_dv_timings - check if two timings match | ||
500 | * @t1 - compare this v4l2_dv_timings struct... | ||
501 | * @t2 - with this struct. | ||
502 | * @pclock_delta - the allowed pixelclock deviation. | ||
503 | * | ||
504 | * Compare t1 with t2 with a given margin of error for the pixelclock. | ||
505 | */ | ||
506 | bool v4l_match_dv_timings(const struct v4l2_dv_timings *t1, | ||
507 | const struct v4l2_dv_timings *t2, | ||
508 | unsigned pclock_delta) | ||
509 | { | ||
510 | if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120) | ||
511 | return false; | ||
512 | if (t1->bt.width == t2->bt.width && | ||
513 | t1->bt.height == t2->bt.height && | ||
514 | t1->bt.interlaced == t2->bt.interlaced && | ||
515 | t1->bt.polarities == t2->bt.polarities && | ||
516 | t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta && | ||
517 | t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta && | ||
518 | t1->bt.hfrontporch == t2->bt.hfrontporch && | ||
519 | t1->bt.vfrontporch == t2->bt.vfrontporch && | ||
520 | t1->bt.vsync == t2->bt.vsync && | ||
521 | t1->bt.vbackporch == t2->bt.vbackporch && | ||
522 | (!t1->bt.interlaced || | ||
523 | (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch && | ||
524 | t1->bt.il_vsync == t2->bt.il_vsync && | ||
525 | t1->bt.il_vbackporch == t2->bt.il_vbackporch))) | ||
526 | return true; | ||
527 | return false; | ||
528 | } | ||
529 | EXPORT_SYMBOL_GPL(v4l_match_dv_timings); | ||
530 | |||
531 | /* | ||
532 | * CVT defines | ||
533 | * Based on Coordinated Video Timings Standard | ||
534 | * version 1.1 September 10, 2003 | ||
535 | */ | ||
536 | |||
537 | #define CVT_PXL_CLK_GRAN 250000 /* pixel clock granularity */ | ||
538 | |||
539 | /* Normal blanking */ | ||
540 | #define CVT_MIN_V_BPORCH 7 /* lines */ | ||
541 | #define CVT_MIN_V_PORCH_RND 3 /* lines */ | ||
542 | #define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | ||
543 | |||
544 | /* Normal blanking for CVT uses GTF to calculate horizontal blanking */ | ||
545 | #define CVT_CELL_GRAN 8 /* character cell granularity */ | ||
546 | #define CVT_M 600 /* blanking formula gradient */ | ||
547 | #define CVT_C 40 /* blanking formula offset */ | ||
548 | #define CVT_K 128 /* blanking formula scaling factor */ | ||
549 | #define CVT_J 20 /* blanking formula scaling factor */ | ||
550 | #define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J) | ||
551 | #define CVT_M_PRIME (CVT_K * CVT_M / 256) | ||
552 | |||
553 | /* Reduced Blanking */ | ||
554 | #define CVT_RB_MIN_V_BPORCH 7 /* lines */ | ||
555 | #define CVT_RB_V_FPORCH 3 /* lines */ | ||
556 | #define CVT_RB_MIN_V_BLANK 460 /* us */ | ||
557 | #define CVT_RB_H_SYNC 32 /* pixels */ | ||
558 | #define CVT_RB_H_BPORCH 80 /* pixels */ | ||
559 | #define CVT_RB_H_BLANK 160 /* pixels */ | ||
560 | |||
561 | /** v4l2_detect_cvt - detect if the given timings follow the CVT standard | ||
562 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
563 | * @hfreq - the horizontal frequency in Hz. | ||
564 | * @vsync - the height of the vertical sync in lines. | ||
565 | * @polarities - the horizontal and vertical polarities (same as struct | ||
566 | * v4l2_bt_timings polarities). | ||
567 | * @fmt - the resulting timings. | ||
568 | * | ||
569 | * This function will attempt to detect if the given values correspond to a | ||
570 | * valid CVT format. If so, then it will return true, and fmt will be filled | ||
571 | * in with the found CVT timings. | ||
572 | */ | ||
573 | bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | ||
574 | u32 polarities, struct v4l2_dv_timings *fmt) | ||
575 | { | ||
576 | int v_fp, v_bp, h_fp, h_bp, hsync; | ||
577 | int frame_width, image_height, image_width; | ||
578 | bool reduced_blanking; | ||
579 | unsigned pix_clk; | ||
580 | |||
581 | if (vsync < 4 || vsync > 7) | ||
582 | return false; | ||
583 | |||
584 | if (polarities == V4L2_DV_VSYNC_POS_POL) | ||
585 | reduced_blanking = false; | ||
586 | else if (polarities == V4L2_DV_HSYNC_POS_POL) | ||
587 | reduced_blanking = true; | ||
588 | else | ||
589 | return false; | ||
590 | |||
591 | /* Vertical */ | ||
592 | if (reduced_blanking) { | ||
593 | v_fp = CVT_RB_V_FPORCH; | ||
594 | v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 999999) / 1000000; | ||
595 | v_bp -= vsync + v_fp; | ||
596 | |||
597 | if (v_bp < CVT_RB_MIN_V_BPORCH) | ||
598 | v_bp = CVT_RB_MIN_V_BPORCH; | ||
599 | } else { | ||
600 | v_fp = CVT_MIN_V_PORCH_RND; | ||
601 | v_bp = (CVT_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; | ||
602 | |||
603 | if (v_bp < CVT_MIN_V_BPORCH) | ||
604 | v_bp = CVT_MIN_V_BPORCH; | ||
605 | } | ||
606 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
607 | |||
608 | /* Aspect ratio based on vsync */ | ||
609 | switch (vsync) { | ||
610 | case 4: | ||
611 | image_width = (image_height * 4) / 3; | ||
612 | break; | ||
613 | case 5: | ||
614 | image_width = (image_height * 16) / 9; | ||
615 | break; | ||
616 | case 6: | ||
617 | image_width = (image_height * 16) / 10; | ||
618 | break; | ||
619 | case 7: | ||
620 | /* special case */ | ||
621 | if (image_height == 1024) | ||
622 | image_width = (image_height * 5) / 4; | ||
623 | else if (image_height == 768) | ||
624 | image_width = (image_height * 15) / 9; | ||
625 | else | ||
626 | return false; | ||
627 | break; | ||
628 | default: | ||
629 | return false; | ||
630 | } | ||
631 | |||
632 | image_width = image_width & ~7; | ||
633 | |||
634 | /* Horizontal */ | ||
635 | if (reduced_blanking) { | ||
636 | pix_clk = (image_width + CVT_RB_H_BLANK) * hfreq; | ||
637 | pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; | ||
638 | |||
639 | h_bp = CVT_RB_H_BPORCH; | ||
640 | hsync = CVT_RB_H_SYNC; | ||
641 | h_fp = CVT_RB_H_BLANK - h_bp - hsync; | ||
642 | |||
643 | frame_width = image_width + CVT_RB_H_BLANK; | ||
644 | } else { | ||
645 | int h_blank; | ||
646 | unsigned ideal_duty_cycle = CVT_C_PRIME - (CVT_M_PRIME * 1000) / hfreq; | ||
647 | |||
648 | h_blank = (image_width * ideal_duty_cycle + (100 - ideal_duty_cycle) / 2) / | ||
649 | (100 - ideal_duty_cycle); | ||
650 | h_blank = h_blank - h_blank % (2 * CVT_CELL_GRAN); | ||
651 | |||
652 | if (h_blank * 100 / image_width < 20) { | ||
653 | h_blank = image_width / 5; | ||
654 | h_blank = (h_blank + 0x7) & ~0x7; | ||
655 | } | ||
656 | |||
657 | pix_clk = (image_width + h_blank) * hfreq; | ||
658 | pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; | ||
659 | |||
660 | h_bp = h_blank / 2; | ||
661 | frame_width = image_width + h_blank; | ||
662 | |||
663 | hsync = (frame_width * 8 + 50) / 100; | ||
664 | hsync = hsync - hsync % CVT_CELL_GRAN; | ||
665 | h_fp = h_blank - hsync - h_bp; | ||
666 | } | ||
667 | |||
668 | fmt->bt.polarities = polarities; | ||
669 | fmt->bt.width = image_width; | ||
670 | fmt->bt.height = image_height; | ||
671 | fmt->bt.hfrontporch = h_fp; | ||
672 | fmt->bt.vfrontporch = v_fp; | ||
673 | fmt->bt.hsync = hsync; | ||
674 | fmt->bt.vsync = vsync; | ||
675 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | ||
676 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
677 | fmt->bt.pixelclock = pix_clk; | ||
678 | fmt->bt.standards = V4L2_DV_BT_STD_CVT; | ||
679 | if (reduced_blanking) | ||
680 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | ||
681 | return true; | ||
682 | } | ||
683 | EXPORT_SYMBOL_GPL(v4l2_detect_cvt); | ||
684 | |||
685 | /* | ||
686 | * GTF defines | ||
687 | * Based on Generalized Timing Formula Standard | ||
688 | * Version 1.1 September 2, 1999 | ||
689 | */ | ||
690 | |||
691 | #define GTF_PXL_CLK_GRAN 250000 /* pixel clock granularity */ | ||
692 | |||
693 | #define GTF_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | ||
694 | #define GTF_V_FP 1 /* vertical front porch (lines) */ | ||
695 | #define GTF_CELL_GRAN 8 /* character cell granularity */ | ||
696 | |||
697 | /* Default */ | ||
698 | #define GTF_D_M 600 /* blanking formula gradient */ | ||
699 | #define GTF_D_C 40 /* blanking formula offset */ | ||
700 | #define GTF_D_K 128 /* blanking formula scaling factor */ | ||
701 | #define GTF_D_J 20 /* blanking formula scaling factor */ | ||
702 | #define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J) | ||
703 | #define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256) | ||
704 | |||
705 | /* Secondary */ | ||
706 | #define GTF_S_M 3600 /* blanking formula gradient */ | ||
707 | #define GTF_S_C 40 /* blanking formula offset */ | ||
708 | #define GTF_S_K 128 /* blanking formula scaling factor */ | ||
709 | #define GTF_S_J 35 /* blanking formula scaling factor */ | ||
710 | #define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J) | ||
711 | #define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256) | ||
712 | |||
713 | /** v4l2_detect_gtf - detect if the given timings follow the GTF standard | ||
714 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
715 | * @hfreq - the horizontal frequency in Hz. | ||
716 | * @vsync - the height of the vertical sync in lines. | ||
717 | * @polarities - the horizontal and vertical polarities (same as struct | ||
718 | * v4l2_bt_timings polarities). | ||
719 | * @aspect - preferred aspect ratio. GTF has no method of determining the | ||
720 | * aspect ratio in order to derive the image width from the | ||
721 | * image height, so it has to be passed explicitly. Usually | ||
722 | * the native screen aspect ratio is used for this. If it | ||
723 | * is not filled in correctly, then 16:9 will be assumed. | ||
724 | * @fmt - the resulting timings. | ||
725 | * | ||
726 | * This function will attempt to detect if the given values correspond to a | ||
727 | * valid GTF format. If so, then it will return true, and fmt will be filled | ||
728 | * in with the found GTF timings. | ||
729 | */ | ||
730 | bool v4l2_detect_gtf(unsigned frame_height, | ||
731 | unsigned hfreq, | ||
732 | unsigned vsync, | ||
733 | u32 polarities, | ||
734 | struct v4l2_fract aspect, | ||
735 | struct v4l2_dv_timings *fmt) | ||
736 | { | ||
737 | int pix_clk; | ||
738 | int v_fp, v_bp, h_fp, hsync; | ||
739 | int frame_width, image_height, image_width; | ||
740 | bool default_gtf; | ||
741 | int h_blank; | ||
742 | |||
743 | if (vsync != 3) | ||
744 | return false; | ||
745 | |||
746 | if (polarities == V4L2_DV_VSYNC_POS_POL) | ||
747 | default_gtf = true; | ||
748 | else if (polarities == V4L2_DV_HSYNC_POS_POL) | ||
749 | default_gtf = false; | ||
750 | else | ||
751 | return false; | ||
752 | |||
753 | /* Vertical */ | ||
754 | v_fp = GTF_V_FP; | ||
755 | v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; | ||
756 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
757 | |||
758 | if (aspect.numerator == 0 || aspect.denominator == 0) { | ||
759 | aspect.numerator = 16; | ||
760 | aspect.denominator = 9; | ||
761 | } | ||
762 | image_width = ((image_height * aspect.numerator) / aspect.denominator); | ||
763 | |||
764 | /* Horizontal */ | ||
765 | if (default_gtf) | ||
766 | h_blank = ((image_width * GTF_D_C_PRIME * hfreq) - | ||
767 | (image_width * GTF_D_M_PRIME * 1000) + | ||
768 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) / | ||
769 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000); | ||
770 | else | ||
771 | h_blank = ((image_width * GTF_S_C_PRIME * hfreq) - | ||
772 | (image_width * GTF_S_M_PRIME * 1000) + | ||
773 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) / | ||
774 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000); | ||
775 | |||
776 | h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN); | ||
777 | frame_width = image_width + h_blank; | ||
778 | |||
779 | pix_clk = (image_width + h_blank) * hfreq; | ||
780 | pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN; | ||
781 | |||
782 | hsync = (frame_width * 8 + 50) / 100; | ||
783 | hsync = hsync - hsync % GTF_CELL_GRAN; | ||
784 | |||
785 | h_fp = h_blank / 2 - hsync; | ||
786 | |||
787 | fmt->bt.polarities = polarities; | ||
788 | fmt->bt.width = image_width; | ||
789 | fmt->bt.height = image_height; | ||
790 | fmt->bt.hfrontporch = h_fp; | ||
791 | fmt->bt.vfrontporch = v_fp; | ||
792 | fmt->bt.hsync = hsync; | ||
793 | fmt->bt.vsync = vsync; | ||
794 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | ||
795 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
796 | fmt->bt.pixelclock = pix_clk; | ||
797 | fmt->bt.standards = V4L2_DV_BT_STD_GTF; | ||
798 | if (!default_gtf) | ||
799 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | ||
800 | return true; | ||
801 | } | ||
802 | EXPORT_SYMBOL_GPL(v4l2_detect_gtf); | ||
803 | |||
804 | /** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes | ||
805 | * 0x15 and 0x16 from the EDID. | ||
806 | * @hor_landscape - byte 0x15 from the EDID. | ||
807 | * @vert_portrait - byte 0x16 from the EDID. | ||
808 | * | ||
809 | * Determines the aspect ratio from the EDID. | ||
810 | * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2: | ||
811 | * "Horizontal and Vertical Screen Size or Aspect Ratio" | ||
812 | */ | ||
813 | struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait) | ||
814 | { | ||
815 | struct v4l2_fract aspect = { 16, 9 }; | ||
816 | u32 tmp; | ||
817 | u8 ratio; | ||
818 | |||
819 | /* Nothing filled in, fallback to 16:9 */ | ||
820 | if (!hor_landscape && !vert_portrait) | ||
821 | return aspect; | ||
822 | /* Both filled in, so they are interpreted as the screen size in cm */ | ||
823 | if (hor_landscape && vert_portrait) { | ||
824 | aspect.numerator = hor_landscape; | ||
825 | aspect.denominator = vert_portrait; | ||
826 | return aspect; | ||
827 | } | ||
828 | /* Only one is filled in, so interpret them as a ratio: | ||
829 | (val + 99) / 100 */ | ||
830 | ratio = hor_landscape | vert_portrait; | ||
831 | /* Change some rounded values into the exact aspect ratio */ | ||
832 | if (ratio == 79) { | ||
833 | aspect.numerator = 16; | ||
834 | aspect.denominator = 9; | ||
835 | } else if (ratio == 34) { | ||
836 | aspect.numerator = 4; | ||
837 | aspect.numerator = 3; | ||
838 | } else if (ratio == 68) { | ||
839 | aspect.numerator = 15; | ||
840 | aspect.numerator = 9; | ||
841 | } else { | ||
842 | aspect.numerator = hor_landscape + 99; | ||
843 | aspect.denominator = 100; | ||
844 | } | ||
845 | if (hor_landscape) | ||
846 | return aspect; | ||
847 | /* The aspect ratio is for portrait, so swap numerator and denominator */ | ||
848 | tmp = aspect.denominator; | ||
849 | aspect.denominator = aspect.numerator; | ||
850 | aspect.numerator = tmp; | ||
851 | return aspect; | ||
852 | } | ||
853 | EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio); | ||
854 | |||
855 | const struct v4l2_frmsize_discrete *v4l2_find_nearest_format( | 498 | const struct v4l2_frmsize_discrete *v4l2_find_nearest_format( |
856 | const struct v4l2_discrete_probe *probe, | 499 | const struct v4l2_discrete_probe *probe, |
857 | s32 width, s32 height) | 500 | s32 width, s32 height) |
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index fccd08b66d1a..c3f080388684 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | |||
@@ -424,6 +424,12 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
424 | NULL, | 424 | NULL, |
425 | }; | 425 | }; |
426 | 426 | ||
427 | static const char * const vpx_golden_frame_sel[] = { | ||
428 | "Use Previous Frame", | ||
429 | "Use Previous Specific Frame", | ||
430 | NULL, | ||
431 | }; | ||
432 | |||
427 | static const char * const flash_led_mode[] = { | 433 | static const char * const flash_led_mode[] = { |
428 | "Off", | 434 | "Off", |
429 | "Flash", | 435 | "Flash", |
@@ -538,6 +544,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
538 | return mpeg_mpeg4_level; | 544 | return mpeg_mpeg4_level; |
539 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: | 545 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
540 | return mpeg4_profile; | 546 | return mpeg4_profile; |
547 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: | ||
548 | return vpx_golden_frame_sel; | ||
541 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: | 549 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: |
542 | return jpeg_chroma_subsampling; | 550 | return jpeg_chroma_subsampling; |
543 | case V4L2_CID_DV_TX_MODE: | 551 | case V4L2_CID_DV_TX_MODE: |
@@ -552,6 +560,33 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
552 | } | 560 | } |
553 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); | 561 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); |
554 | 562 | ||
563 | #define __v4l2_qmenu_int_len(arr, len) ({ *(len) = ARRAY_SIZE(arr); arr; }) | ||
564 | /* | ||
565 | * Returns NULL or an s64 type array containing the menu for given | ||
566 | * control ID. The total number of the menu items is returned in @len. | ||
567 | */ | ||
568 | const s64 const *v4l2_ctrl_get_int_menu(u32 id, u32 *len) | ||
569 | { | ||
570 | static const s64 const qmenu_int_vpx_num_partitions[] = { | ||
571 | 1, 2, 4, 8, | ||
572 | }; | ||
573 | |||
574 | static const s64 const qmenu_int_vpx_num_ref_frames[] = { | ||
575 | 1, 2, 3, | ||
576 | }; | ||
577 | |||
578 | switch (id) { | ||
579 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: | ||
580 | return __v4l2_qmenu_int_len(qmenu_int_vpx_num_partitions, len); | ||
581 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: | ||
582 | return __v4l2_qmenu_int_len(qmenu_int_vpx_num_ref_frames, len); | ||
583 | default: | ||
584 | *len = 0; | ||
585 | return NULL; | ||
586 | }; | ||
587 | } | ||
588 | EXPORT_SYMBOL(v4l2_ctrl_get_int_menu); | ||
589 | |||
555 | /* Return the control name. */ | 590 | /* Return the control name. */ |
556 | const char *v4l2_ctrl_get_name(u32 id) | 591 | const char *v4l2_ctrl_get_name(u32 id) |
557 | { | 592 | { |
@@ -600,9 +635,11 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
600 | case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; | 635 | case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; |
601 | case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr"; | 636 | case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr"; |
602 | 637 | ||
603 | /* MPEG controls */ | 638 | /* Codec controls */ |
639 | /* The MPEG controls are applicable to all codec controls | ||
640 | * and the 'MPEG' part of the define is historical */ | ||
604 | /* Keep the order of the 'case's the same as in videodev2.h! */ | 641 | /* Keep the order of the 'case's the same as in videodev2.h! */ |
605 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; | 642 | case V4L2_CID_MPEG_CLASS: return "Codec Controls"; |
606 | case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; | 643 | case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; |
607 | case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; | 644 | case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; |
608 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; | 645 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; |
@@ -700,6 +737,15 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
700 | case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control"; | 737 | case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control"; |
701 | case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header"; | 738 | case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header"; |
702 | 739 | ||
740 | /* VPX controls */ | ||
741 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions"; | ||
742 | case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4: return "VPX Intra Mode Decision Disable"; | ||
743 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: return "VPX No. of Refs for P Frame"; | ||
744 | case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL: return "VPX Loop Filter Level Range"; | ||
745 | case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS: return "VPX Deblocking Effect Control"; | ||
746 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD: return "VPX Golden Frame Refresh Period"; | ||
747 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: return "VPX Golden Frame Indicator"; | ||
748 | |||
703 | /* CAMERA controls */ | 749 | /* CAMERA controls */ |
704 | /* Keep the order of the 'case's the same as in videodev2.h! */ | 750 | /* Keep the order of the 'case's the same as in videodev2.h! */ |
705 | case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; | 751 | case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; |
@@ -914,6 +960,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
914 | case V4L2_CID_DV_RX_RGB_RANGE: | 960 | case V4L2_CID_DV_RX_RGB_RANGE: |
915 | case V4L2_CID_TEST_PATTERN: | 961 | case V4L2_CID_TEST_PATTERN: |
916 | case V4L2_CID_TUNE_DEEMPHASIS: | 962 | case V4L2_CID_TUNE_DEEMPHASIS: |
963 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: | ||
917 | *type = V4L2_CTRL_TYPE_MENU; | 964 | *type = V4L2_CTRL_TYPE_MENU; |
918 | break; | 965 | break; |
919 | case V4L2_CID_LINK_FREQ: | 966 | case V4L2_CID_LINK_FREQ: |
@@ -925,6 +972,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
925 | break; | 972 | break; |
926 | case V4L2_CID_ISO_SENSITIVITY: | 973 | case V4L2_CID_ISO_SENSITIVITY: |
927 | case V4L2_CID_AUTO_EXPOSURE_BIAS: | 974 | case V4L2_CID_AUTO_EXPOSURE_BIAS: |
975 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: | ||
976 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: | ||
928 | *type = V4L2_CTRL_TYPE_INTEGER_MENU; | 977 | *type = V4L2_CTRL_TYPE_INTEGER_MENU; |
929 | break; | 978 | break; |
930 | case V4L2_CID_USER_CLASS: | 979 | case V4L2_CID_USER_CLASS: |
@@ -1712,7 +1761,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, | |||
1712 | const struct v4l2_ctrl_ops *ops, | 1761 | const struct v4l2_ctrl_ops *ops, |
1713 | u32 id, s32 max, s32 mask, s32 def) | 1762 | u32 id, s32 max, s32 mask, s32 def) |
1714 | { | 1763 | { |
1715 | const char * const *qmenu = v4l2_ctrl_get_menu(id); | 1764 | const char * const *qmenu = NULL; |
1765 | const s64 *qmenu_int = NULL; | ||
1766 | unsigned int qmenu_int_len = 0; | ||
1716 | const char *name; | 1767 | const char *name; |
1717 | enum v4l2_ctrl_type type; | 1768 | enum v4l2_ctrl_type type; |
1718 | s32 min; | 1769 | s32 min; |
@@ -1720,12 +1771,18 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, | |||
1720 | u32 flags; | 1771 | u32 flags; |
1721 | 1772 | ||
1722 | v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); | 1773 | v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); |
1723 | if (type != V4L2_CTRL_TYPE_MENU) { | 1774 | |
1775 | if (type == V4L2_CTRL_TYPE_MENU) | ||
1776 | qmenu = v4l2_ctrl_get_menu(id); | ||
1777 | else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) | ||
1778 | qmenu_int = v4l2_ctrl_get_int_menu(id, &qmenu_int_len); | ||
1779 | |||
1780 | if ((!qmenu && !qmenu_int) || (qmenu_int && max > qmenu_int_len)) { | ||
1724 | handler_set_err(hdl, -EINVAL); | 1781 | handler_set_err(hdl, -EINVAL); |
1725 | return NULL; | 1782 | return NULL; |
1726 | } | 1783 | } |
1727 | return v4l2_ctrl_new(hdl, ops, id, name, type, | 1784 | return v4l2_ctrl_new(hdl, ops, id, name, type, |
1728 | 0, max, mask, def, flags, qmenu, NULL, NULL); | 1785 | 0, max, mask, def, flags, qmenu, qmenu_int, NULL); |
1729 | } | 1786 | } |
1730 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); | 1787 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); |
1731 | 1788 | ||
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index b0f49b014bc5..b5aaaac427ad 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c | |||
@@ -872,6 +872,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr, | |||
872 | 872 | ||
873 | /* Should not happen since we thought this minor was free */ | 873 | /* Should not happen since we thought this minor was free */ |
874 | WARN_ON(video_device[vdev->minor] != NULL); | 874 | WARN_ON(video_device[vdev->minor] != NULL); |
875 | video_device[vdev->minor] = vdev; | ||
875 | vdev->index = get_index(vdev); | 876 | vdev->index = get_index(vdev); |
876 | mutex_unlock(&videodev_lock); | 877 | mutex_unlock(&videodev_lock); |
877 | 878 | ||
@@ -934,9 +935,6 @@ int __video_register_device(struct video_device *vdev, int type, int nr, | |||
934 | #endif | 935 | #endif |
935 | /* Part 6: Activate this minor. The char device can now be used. */ | 936 | /* Part 6: Activate this minor. The char device can now be used. */ |
936 | set_bit(V4L2_FL_REGISTERED, &vdev->flags); | 937 | set_bit(V4L2_FL_REGISTERED, &vdev->flags); |
937 | mutex_lock(&videodev_lock); | ||
938 | video_device[vdev->minor] = vdev; | ||
939 | mutex_unlock(&videodev_lock); | ||
940 | 938 | ||
941 | return 0; | 939 | return 0; |
942 | 940 | ||
@@ -944,6 +942,7 @@ cleanup: | |||
944 | mutex_lock(&videodev_lock); | 942 | mutex_lock(&videodev_lock); |
945 | if (vdev->cdev) | 943 | if (vdev->cdev) |
946 | cdev_del(vdev->cdev); | 944 | cdev_del(vdev->cdev); |
945 | video_device[vdev->minor] = NULL; | ||
947 | devnode_clear(vdev); | 946 | devnode_clear(vdev); |
948 | mutex_unlock(&videodev_lock); | 947 | mutex_unlock(&videodev_lock); |
949 | /* Mark this video device as never having been registered. */ | 948 | /* Mark this video device as never having been registered. */ |
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c new file mode 100644 index 000000000000..ee52b9f4a944 --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c | |||
@@ -0,0 +1,609 @@ | |||
1 | /* | ||
2 | * v4l2-dv-timings - dv-timings helper functions | ||
3 | * | ||
4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you may redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
17 | * SOFTWARE. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/videodev2.h> | ||
26 | #include <linux/v4l2-dv-timings.h> | ||
27 | #include <media/v4l2-dv-timings.h> | ||
28 | |||
29 | const struct v4l2_dv_timings v4l2_dv_timings_presets[] = { | ||
30 | V4L2_DV_BT_CEA_640X480P59_94, | ||
31 | V4L2_DV_BT_CEA_720X480I59_94, | ||
32 | V4L2_DV_BT_CEA_720X480P59_94, | ||
33 | V4L2_DV_BT_CEA_720X576I50, | ||
34 | V4L2_DV_BT_CEA_720X576P50, | ||
35 | V4L2_DV_BT_CEA_1280X720P24, | ||
36 | V4L2_DV_BT_CEA_1280X720P25, | ||
37 | V4L2_DV_BT_CEA_1280X720P30, | ||
38 | V4L2_DV_BT_CEA_1280X720P50, | ||
39 | V4L2_DV_BT_CEA_1280X720P60, | ||
40 | V4L2_DV_BT_CEA_1920X1080P24, | ||
41 | V4L2_DV_BT_CEA_1920X1080P25, | ||
42 | V4L2_DV_BT_CEA_1920X1080P30, | ||
43 | V4L2_DV_BT_CEA_1920X1080I50, | ||
44 | V4L2_DV_BT_CEA_1920X1080P50, | ||
45 | V4L2_DV_BT_CEA_1920X1080I60, | ||
46 | V4L2_DV_BT_CEA_1920X1080P60, | ||
47 | V4L2_DV_BT_DMT_640X350P85, | ||
48 | V4L2_DV_BT_DMT_640X400P85, | ||
49 | V4L2_DV_BT_DMT_720X400P85, | ||
50 | V4L2_DV_BT_DMT_640X480P72, | ||
51 | V4L2_DV_BT_DMT_640X480P75, | ||
52 | V4L2_DV_BT_DMT_640X480P85, | ||
53 | V4L2_DV_BT_DMT_800X600P56, | ||
54 | V4L2_DV_BT_DMT_800X600P60, | ||
55 | V4L2_DV_BT_DMT_800X600P72, | ||
56 | V4L2_DV_BT_DMT_800X600P75, | ||
57 | V4L2_DV_BT_DMT_800X600P85, | ||
58 | V4L2_DV_BT_DMT_800X600P120_RB, | ||
59 | V4L2_DV_BT_DMT_848X480P60, | ||
60 | V4L2_DV_BT_DMT_1024X768I43, | ||
61 | V4L2_DV_BT_DMT_1024X768P60, | ||
62 | V4L2_DV_BT_DMT_1024X768P70, | ||
63 | V4L2_DV_BT_DMT_1024X768P75, | ||
64 | V4L2_DV_BT_DMT_1024X768P85, | ||
65 | V4L2_DV_BT_DMT_1024X768P120_RB, | ||
66 | V4L2_DV_BT_DMT_1152X864P75, | ||
67 | V4L2_DV_BT_DMT_1280X768P60_RB, | ||
68 | V4L2_DV_BT_DMT_1280X768P60, | ||
69 | V4L2_DV_BT_DMT_1280X768P75, | ||
70 | V4L2_DV_BT_DMT_1280X768P85, | ||
71 | V4L2_DV_BT_DMT_1280X768P120_RB, | ||
72 | V4L2_DV_BT_DMT_1280X800P60_RB, | ||
73 | V4L2_DV_BT_DMT_1280X800P60, | ||
74 | V4L2_DV_BT_DMT_1280X800P75, | ||
75 | V4L2_DV_BT_DMT_1280X800P85, | ||
76 | V4L2_DV_BT_DMT_1280X800P120_RB, | ||
77 | V4L2_DV_BT_DMT_1280X960P60, | ||
78 | V4L2_DV_BT_DMT_1280X960P85, | ||
79 | V4L2_DV_BT_DMT_1280X960P120_RB, | ||
80 | V4L2_DV_BT_DMT_1280X1024P60, | ||
81 | V4L2_DV_BT_DMT_1280X1024P75, | ||
82 | V4L2_DV_BT_DMT_1280X1024P85, | ||
83 | V4L2_DV_BT_DMT_1280X1024P120_RB, | ||
84 | V4L2_DV_BT_DMT_1360X768P60, | ||
85 | V4L2_DV_BT_DMT_1360X768P120_RB, | ||
86 | V4L2_DV_BT_DMT_1366X768P60, | ||
87 | V4L2_DV_BT_DMT_1366X768P60_RB, | ||
88 | V4L2_DV_BT_DMT_1400X1050P60_RB, | ||
89 | V4L2_DV_BT_DMT_1400X1050P60, | ||
90 | V4L2_DV_BT_DMT_1400X1050P75, | ||
91 | V4L2_DV_BT_DMT_1400X1050P85, | ||
92 | V4L2_DV_BT_DMT_1400X1050P120_RB, | ||
93 | V4L2_DV_BT_DMT_1440X900P60_RB, | ||
94 | V4L2_DV_BT_DMT_1440X900P60, | ||
95 | V4L2_DV_BT_DMT_1440X900P75, | ||
96 | V4L2_DV_BT_DMT_1440X900P85, | ||
97 | V4L2_DV_BT_DMT_1440X900P120_RB, | ||
98 | V4L2_DV_BT_DMT_1600X900P60_RB, | ||
99 | V4L2_DV_BT_DMT_1600X1200P60, | ||
100 | V4L2_DV_BT_DMT_1600X1200P65, | ||
101 | V4L2_DV_BT_DMT_1600X1200P70, | ||
102 | V4L2_DV_BT_DMT_1600X1200P75, | ||
103 | V4L2_DV_BT_DMT_1600X1200P85, | ||
104 | V4L2_DV_BT_DMT_1600X1200P120_RB, | ||
105 | V4L2_DV_BT_DMT_1680X1050P60_RB, | ||
106 | V4L2_DV_BT_DMT_1680X1050P60, | ||
107 | V4L2_DV_BT_DMT_1680X1050P75, | ||
108 | V4L2_DV_BT_DMT_1680X1050P85, | ||
109 | V4L2_DV_BT_DMT_1680X1050P120_RB, | ||
110 | V4L2_DV_BT_DMT_1792X1344P60, | ||
111 | V4L2_DV_BT_DMT_1792X1344P75, | ||
112 | V4L2_DV_BT_DMT_1792X1344P120_RB, | ||
113 | V4L2_DV_BT_DMT_1856X1392P60, | ||
114 | V4L2_DV_BT_DMT_1856X1392P75, | ||
115 | V4L2_DV_BT_DMT_1856X1392P120_RB, | ||
116 | V4L2_DV_BT_DMT_1920X1200P60_RB, | ||
117 | V4L2_DV_BT_DMT_1920X1200P60, | ||
118 | V4L2_DV_BT_DMT_1920X1200P75, | ||
119 | V4L2_DV_BT_DMT_1920X1200P85, | ||
120 | V4L2_DV_BT_DMT_1920X1200P120_RB, | ||
121 | V4L2_DV_BT_DMT_1920X1440P60, | ||
122 | V4L2_DV_BT_DMT_1920X1440P75, | ||
123 | V4L2_DV_BT_DMT_1920X1440P120_RB, | ||
124 | V4L2_DV_BT_DMT_2048X1152P60_RB, | ||
125 | V4L2_DV_BT_DMT_2560X1600P60_RB, | ||
126 | V4L2_DV_BT_DMT_2560X1600P60, | ||
127 | V4L2_DV_BT_DMT_2560X1600P75, | ||
128 | V4L2_DV_BT_DMT_2560X1600P85, | ||
129 | V4L2_DV_BT_DMT_2560X1600P120_RB, | ||
130 | { } | ||
131 | }; | ||
132 | EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets); | ||
133 | |||
134 | bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, | ||
135 | const struct v4l2_dv_timings_cap *dvcap, | ||
136 | v4l2_check_dv_timings_fnc fnc, | ||
137 | void *fnc_handle) | ||
138 | { | ||
139 | const struct v4l2_bt_timings *bt = &t->bt; | ||
140 | const struct v4l2_bt_timings_cap *cap = &dvcap->bt; | ||
141 | u32 caps = cap->capabilities; | ||
142 | |||
143 | if (t->type != V4L2_DV_BT_656_1120) | ||
144 | return false; | ||
145 | if (t->type != dvcap->type || | ||
146 | bt->height < cap->min_height || | ||
147 | bt->height > cap->max_height || | ||
148 | bt->width < cap->min_width || | ||
149 | bt->width > cap->max_width || | ||
150 | bt->pixelclock < cap->min_pixelclock || | ||
151 | bt->pixelclock > cap->max_pixelclock || | ||
152 | (cap->standards && !(bt->standards & cap->standards)) || | ||
153 | (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || | ||
154 | (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) | ||
155 | return false; | ||
156 | return fnc == NULL || fnc(t, fnc_handle); | ||
157 | } | ||
158 | EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings); | ||
159 | |||
160 | int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, | ||
161 | const struct v4l2_dv_timings_cap *cap, | ||
162 | v4l2_check_dv_timings_fnc fnc, | ||
163 | void *fnc_handle) | ||
164 | { | ||
165 | u32 i, idx; | ||
166 | |||
167 | memset(t->reserved, 0, sizeof(t->reserved)); | ||
168 | for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) { | ||
169 | if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, | ||
170 | fnc, fnc_handle) && | ||
171 | idx++ == t->index) { | ||
172 | t->timings = v4l2_dv_timings_presets[i]; | ||
173 | return 0; | ||
174 | } | ||
175 | } | ||
176 | return -EINVAL; | ||
177 | } | ||
178 | EXPORT_SYMBOL_GPL(v4l2_enum_dv_timings_cap); | ||
179 | |||
180 | bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, | ||
181 | const struct v4l2_dv_timings_cap *cap, | ||
182 | unsigned pclock_delta, | ||
183 | v4l2_check_dv_timings_fnc fnc, | ||
184 | void *fnc_handle) | ||
185 | { | ||
186 | int i; | ||
187 | |||
188 | if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle)) | ||
189 | return false; | ||
190 | |||
191 | for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) { | ||
192 | if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, | ||
193 | fnc, fnc_handle) && | ||
194 | v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i, | ||
195 | pclock_delta)) { | ||
196 | *t = v4l2_dv_timings_presets[i]; | ||
197 | return true; | ||
198 | } | ||
199 | } | ||
200 | return false; | ||
201 | } | ||
202 | EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cap); | ||
203 | |||
204 | /** | ||
205 | * v4l2_match_dv_timings - check if two timings match | ||
206 | * @t1 - compare this v4l2_dv_timings struct... | ||
207 | * @t2 - with this struct. | ||
208 | * @pclock_delta - the allowed pixelclock deviation. | ||
209 | * | ||
210 | * Compare t1 with t2 with a given margin of error for the pixelclock. | ||
211 | */ | ||
212 | bool v4l2_match_dv_timings(const struct v4l2_dv_timings *t1, | ||
213 | const struct v4l2_dv_timings *t2, | ||
214 | unsigned pclock_delta) | ||
215 | { | ||
216 | if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120) | ||
217 | return false; | ||
218 | if (t1->bt.width == t2->bt.width && | ||
219 | t1->bt.height == t2->bt.height && | ||
220 | t1->bt.interlaced == t2->bt.interlaced && | ||
221 | t1->bt.polarities == t2->bt.polarities && | ||
222 | t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta && | ||
223 | t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta && | ||
224 | t1->bt.hfrontporch == t2->bt.hfrontporch && | ||
225 | t1->bt.vfrontporch == t2->bt.vfrontporch && | ||
226 | t1->bt.vsync == t2->bt.vsync && | ||
227 | t1->bt.vbackporch == t2->bt.vbackporch && | ||
228 | (!t1->bt.interlaced || | ||
229 | (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch && | ||
230 | t1->bt.il_vsync == t2->bt.il_vsync && | ||
231 | t1->bt.il_vbackporch == t2->bt.il_vbackporch))) | ||
232 | return true; | ||
233 | return false; | ||
234 | } | ||
235 | EXPORT_SYMBOL_GPL(v4l2_match_dv_timings); | ||
236 | |||
237 | void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix, | ||
238 | const struct v4l2_dv_timings *t, bool detailed) | ||
239 | { | ||
240 | const struct v4l2_bt_timings *bt = &t->bt; | ||
241 | u32 htot, vtot; | ||
242 | |||
243 | if (t->type != V4L2_DV_BT_656_1120) | ||
244 | return; | ||
245 | |||
246 | htot = V4L2_DV_BT_FRAME_WIDTH(bt); | ||
247 | vtot = V4L2_DV_BT_FRAME_HEIGHT(bt); | ||
248 | |||
249 | if (prefix == NULL) | ||
250 | prefix = ""; | ||
251 | |||
252 | pr_info("%s: %s%ux%u%s%u (%ux%u)\n", dev_prefix, prefix, | ||
253 | bt->width, bt->height, bt->interlaced ? "i" : "p", | ||
254 | (htot * vtot) > 0 ? ((u32)bt->pixelclock / (htot * vtot)) : 0, | ||
255 | htot, vtot); | ||
256 | |||
257 | if (!detailed) | ||
258 | return; | ||
259 | |||
260 | pr_info("%s: horizontal: fp = %u, %ssync = %u, bp = %u\n", | ||
261 | dev_prefix, bt->hfrontporch, | ||
262 | (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", | ||
263 | bt->hsync, bt->hbackporch); | ||
264 | pr_info("%s: vertical: fp = %u, %ssync = %u, bp = %u\n", | ||
265 | dev_prefix, bt->vfrontporch, | ||
266 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", | ||
267 | bt->vsync, bt->vbackporch); | ||
268 | pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock); | ||
269 | pr_info("%s: flags (0x%x):%s%s%s%s\n", dev_prefix, bt->flags, | ||
270 | (bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ? | ||
271 | " REDUCED_BLANKING" : "", | ||
272 | (bt->flags & V4L2_DV_FL_CAN_REDUCE_FPS) ? | ||
273 | " CAN_REDUCE_FPS" : "", | ||
274 | (bt->flags & V4L2_DV_FL_REDUCED_FPS) ? | ||
275 | " REDUCED_FPS" : "", | ||
276 | (bt->flags & V4L2_DV_FL_HALF_LINE) ? | ||
277 | " HALF_LINE" : ""); | ||
278 | pr_info("%s: standards (0x%x):%s%s%s%s\n", dev_prefix, bt->standards, | ||
279 | (bt->standards & V4L2_DV_BT_STD_CEA861) ? " CEA" : "", | ||
280 | (bt->standards & V4L2_DV_BT_STD_DMT) ? " DMT" : "", | ||
281 | (bt->standards & V4L2_DV_BT_STD_CVT) ? " CVT" : "", | ||
282 | (bt->standards & V4L2_DV_BT_STD_GTF) ? " GTF" : ""); | ||
283 | } | ||
284 | EXPORT_SYMBOL_GPL(v4l2_print_dv_timings); | ||
285 | |||
286 | /* | ||
287 | * CVT defines | ||
288 | * Based on Coordinated Video Timings Standard | ||
289 | * version 1.1 September 10, 2003 | ||
290 | */ | ||
291 | |||
292 | #define CVT_PXL_CLK_GRAN 250000 /* pixel clock granularity */ | ||
293 | |||
294 | /* Normal blanking */ | ||
295 | #define CVT_MIN_V_BPORCH 7 /* lines */ | ||
296 | #define CVT_MIN_V_PORCH_RND 3 /* lines */ | ||
297 | #define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | ||
298 | |||
299 | /* Normal blanking for CVT uses GTF to calculate horizontal blanking */ | ||
300 | #define CVT_CELL_GRAN 8 /* character cell granularity */ | ||
301 | #define CVT_M 600 /* blanking formula gradient */ | ||
302 | #define CVT_C 40 /* blanking formula offset */ | ||
303 | #define CVT_K 128 /* blanking formula scaling factor */ | ||
304 | #define CVT_J 20 /* blanking formula scaling factor */ | ||
305 | #define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J) | ||
306 | #define CVT_M_PRIME (CVT_K * CVT_M / 256) | ||
307 | |||
308 | /* Reduced Blanking */ | ||
309 | #define CVT_RB_MIN_V_BPORCH 7 /* lines */ | ||
310 | #define CVT_RB_V_FPORCH 3 /* lines */ | ||
311 | #define CVT_RB_MIN_V_BLANK 460 /* us */ | ||
312 | #define CVT_RB_H_SYNC 32 /* pixels */ | ||
313 | #define CVT_RB_H_BPORCH 80 /* pixels */ | ||
314 | #define CVT_RB_H_BLANK 160 /* pixels */ | ||
315 | |||
316 | /** v4l2_detect_cvt - detect if the given timings follow the CVT standard | ||
317 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
318 | * @hfreq - the horizontal frequency in Hz. | ||
319 | * @vsync - the height of the vertical sync in lines. | ||
320 | * @polarities - the horizontal and vertical polarities (same as struct | ||
321 | * v4l2_bt_timings polarities). | ||
322 | * @fmt - the resulting timings. | ||
323 | * | ||
324 | * This function will attempt to detect if the given values correspond to a | ||
325 | * valid CVT format. If so, then it will return true, and fmt will be filled | ||
326 | * in with the found CVT timings. | ||
327 | */ | ||
328 | bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | ||
329 | u32 polarities, struct v4l2_dv_timings *fmt) | ||
330 | { | ||
331 | int v_fp, v_bp, h_fp, h_bp, hsync; | ||
332 | int frame_width, image_height, image_width; | ||
333 | bool reduced_blanking; | ||
334 | unsigned pix_clk; | ||
335 | |||
336 | if (vsync < 4 || vsync > 7) | ||
337 | return false; | ||
338 | |||
339 | if (polarities == V4L2_DV_VSYNC_POS_POL) | ||
340 | reduced_blanking = false; | ||
341 | else if (polarities == V4L2_DV_HSYNC_POS_POL) | ||
342 | reduced_blanking = true; | ||
343 | else | ||
344 | return false; | ||
345 | |||
346 | /* Vertical */ | ||
347 | if (reduced_blanking) { | ||
348 | v_fp = CVT_RB_V_FPORCH; | ||
349 | v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 1999999) / 1000000; | ||
350 | v_bp -= vsync + v_fp; | ||
351 | |||
352 | if (v_bp < CVT_RB_MIN_V_BPORCH) | ||
353 | v_bp = CVT_RB_MIN_V_BPORCH; | ||
354 | } else { | ||
355 | v_fp = CVT_MIN_V_PORCH_RND; | ||
356 | v_bp = (CVT_MIN_VSYNC_BP * hfreq + 1999999) / 1000000 - vsync; | ||
357 | |||
358 | if (v_bp < CVT_MIN_V_BPORCH) | ||
359 | v_bp = CVT_MIN_V_BPORCH; | ||
360 | } | ||
361 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
362 | |||
363 | /* Aspect ratio based on vsync */ | ||
364 | switch (vsync) { | ||
365 | case 4: | ||
366 | image_width = (image_height * 4) / 3; | ||
367 | break; | ||
368 | case 5: | ||
369 | image_width = (image_height * 16) / 9; | ||
370 | break; | ||
371 | case 6: | ||
372 | image_width = (image_height * 16) / 10; | ||
373 | break; | ||
374 | case 7: | ||
375 | /* special case */ | ||
376 | if (image_height == 1024) | ||
377 | image_width = (image_height * 5) / 4; | ||
378 | else if (image_height == 768) | ||
379 | image_width = (image_height * 15) / 9; | ||
380 | else | ||
381 | return false; | ||
382 | break; | ||
383 | default: | ||
384 | return false; | ||
385 | } | ||
386 | |||
387 | image_width = image_width & ~7; | ||
388 | |||
389 | /* Horizontal */ | ||
390 | if (reduced_blanking) { | ||
391 | pix_clk = (image_width + CVT_RB_H_BLANK) * hfreq; | ||
392 | pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; | ||
393 | |||
394 | h_bp = CVT_RB_H_BPORCH; | ||
395 | hsync = CVT_RB_H_SYNC; | ||
396 | h_fp = CVT_RB_H_BLANK - h_bp - hsync; | ||
397 | |||
398 | frame_width = image_width + CVT_RB_H_BLANK; | ||
399 | } else { | ||
400 | unsigned ideal_duty_cycle_per_myriad = | ||
401 | 100 * CVT_C_PRIME - (CVT_M_PRIME * 100000) / hfreq; | ||
402 | int h_blank; | ||
403 | |||
404 | if (ideal_duty_cycle_per_myriad < 2000) | ||
405 | ideal_duty_cycle_per_myriad = 2000; | ||
406 | |||
407 | h_blank = image_width * ideal_duty_cycle_per_myriad / | ||
408 | (10000 - ideal_duty_cycle_per_myriad); | ||
409 | h_blank = (h_blank / (2 * CVT_CELL_GRAN)) * 2 * CVT_CELL_GRAN; | ||
410 | |||
411 | pix_clk = (image_width + h_blank) * hfreq; | ||
412 | pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; | ||
413 | |||
414 | h_bp = h_blank / 2; | ||
415 | frame_width = image_width + h_blank; | ||
416 | |||
417 | hsync = (frame_width * 8 + 50) / 100; | ||
418 | hsync = hsync - hsync % CVT_CELL_GRAN; | ||
419 | h_fp = h_blank - hsync - h_bp; | ||
420 | } | ||
421 | |||
422 | fmt->type = V4L2_DV_BT_656_1120; | ||
423 | fmt->bt.polarities = polarities; | ||
424 | fmt->bt.width = image_width; | ||
425 | fmt->bt.height = image_height; | ||
426 | fmt->bt.hfrontporch = h_fp; | ||
427 | fmt->bt.vfrontporch = v_fp; | ||
428 | fmt->bt.hsync = hsync; | ||
429 | fmt->bt.vsync = vsync; | ||
430 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | ||
431 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
432 | fmt->bt.pixelclock = pix_clk; | ||
433 | fmt->bt.standards = V4L2_DV_BT_STD_CVT; | ||
434 | if (reduced_blanking) | ||
435 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | ||
436 | return true; | ||
437 | } | ||
438 | EXPORT_SYMBOL_GPL(v4l2_detect_cvt); | ||
439 | |||
440 | /* | ||
441 | * GTF defines | ||
442 | * Based on Generalized Timing Formula Standard | ||
443 | * Version 1.1 September 2, 1999 | ||
444 | */ | ||
445 | |||
446 | #define GTF_PXL_CLK_GRAN 250000 /* pixel clock granularity */ | ||
447 | |||
448 | #define GTF_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | ||
449 | #define GTF_V_FP 1 /* vertical front porch (lines) */ | ||
450 | #define GTF_CELL_GRAN 8 /* character cell granularity */ | ||
451 | |||
452 | /* Default */ | ||
453 | #define GTF_D_M 600 /* blanking formula gradient */ | ||
454 | #define GTF_D_C 40 /* blanking formula offset */ | ||
455 | #define GTF_D_K 128 /* blanking formula scaling factor */ | ||
456 | #define GTF_D_J 20 /* blanking formula scaling factor */ | ||
457 | #define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J) | ||
458 | #define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256) | ||
459 | |||
460 | /* Secondary */ | ||
461 | #define GTF_S_M 3600 /* blanking formula gradient */ | ||
462 | #define GTF_S_C 40 /* blanking formula offset */ | ||
463 | #define GTF_S_K 128 /* blanking formula scaling factor */ | ||
464 | #define GTF_S_J 35 /* blanking formula scaling factor */ | ||
465 | #define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J) | ||
466 | #define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256) | ||
467 | |||
468 | /** v4l2_detect_gtf - detect if the given timings follow the GTF standard | ||
469 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
470 | * @hfreq - the horizontal frequency in Hz. | ||
471 | * @vsync - the height of the vertical sync in lines. | ||
472 | * @polarities - the horizontal and vertical polarities (same as struct | ||
473 | * v4l2_bt_timings polarities). | ||
474 | * @aspect - preferred aspect ratio. GTF has no method of determining the | ||
475 | * aspect ratio in order to derive the image width from the | ||
476 | * image height, so it has to be passed explicitly. Usually | ||
477 | * the native screen aspect ratio is used for this. If it | ||
478 | * is not filled in correctly, then 16:9 will be assumed. | ||
479 | * @fmt - the resulting timings. | ||
480 | * | ||
481 | * This function will attempt to detect if the given values correspond to a | ||
482 | * valid GTF format. If so, then it will return true, and fmt will be filled | ||
483 | * in with the found GTF timings. | ||
484 | */ | ||
485 | bool v4l2_detect_gtf(unsigned frame_height, | ||
486 | unsigned hfreq, | ||
487 | unsigned vsync, | ||
488 | u32 polarities, | ||
489 | struct v4l2_fract aspect, | ||
490 | struct v4l2_dv_timings *fmt) | ||
491 | { | ||
492 | int pix_clk; | ||
493 | int v_fp, v_bp, h_fp, hsync; | ||
494 | int frame_width, image_height, image_width; | ||
495 | bool default_gtf; | ||
496 | int h_blank; | ||
497 | |||
498 | if (vsync != 3) | ||
499 | return false; | ||
500 | |||
501 | if (polarities == V4L2_DV_VSYNC_POS_POL) | ||
502 | default_gtf = true; | ||
503 | else if (polarities == V4L2_DV_HSYNC_POS_POL) | ||
504 | default_gtf = false; | ||
505 | else | ||
506 | return false; | ||
507 | |||
508 | /* Vertical */ | ||
509 | v_fp = GTF_V_FP; | ||
510 | v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; | ||
511 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
512 | |||
513 | if (aspect.numerator == 0 || aspect.denominator == 0) { | ||
514 | aspect.numerator = 16; | ||
515 | aspect.denominator = 9; | ||
516 | } | ||
517 | image_width = ((image_height * aspect.numerator) / aspect.denominator); | ||
518 | |||
519 | /* Horizontal */ | ||
520 | if (default_gtf) | ||
521 | h_blank = ((image_width * GTF_D_C_PRIME * hfreq) - | ||
522 | (image_width * GTF_D_M_PRIME * 1000) + | ||
523 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) / | ||
524 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000); | ||
525 | else | ||
526 | h_blank = ((image_width * GTF_S_C_PRIME * hfreq) - | ||
527 | (image_width * GTF_S_M_PRIME * 1000) + | ||
528 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) / | ||
529 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000); | ||
530 | |||
531 | h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN); | ||
532 | frame_width = image_width + h_blank; | ||
533 | |||
534 | pix_clk = (image_width + h_blank) * hfreq; | ||
535 | pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN; | ||
536 | |||
537 | hsync = (frame_width * 8 + 50) / 100; | ||
538 | hsync = hsync - hsync % GTF_CELL_GRAN; | ||
539 | |||
540 | h_fp = h_blank / 2 - hsync; | ||
541 | |||
542 | fmt->type = V4L2_DV_BT_656_1120; | ||
543 | fmt->bt.polarities = polarities; | ||
544 | fmt->bt.width = image_width; | ||
545 | fmt->bt.height = image_height; | ||
546 | fmt->bt.hfrontporch = h_fp; | ||
547 | fmt->bt.vfrontporch = v_fp; | ||
548 | fmt->bt.hsync = hsync; | ||
549 | fmt->bt.vsync = vsync; | ||
550 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | ||
551 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
552 | fmt->bt.pixelclock = pix_clk; | ||
553 | fmt->bt.standards = V4L2_DV_BT_STD_GTF; | ||
554 | if (!default_gtf) | ||
555 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | ||
556 | return true; | ||
557 | } | ||
558 | EXPORT_SYMBOL_GPL(v4l2_detect_gtf); | ||
559 | |||
560 | /** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes | ||
561 | * 0x15 and 0x16 from the EDID. | ||
562 | * @hor_landscape - byte 0x15 from the EDID. | ||
563 | * @vert_portrait - byte 0x16 from the EDID. | ||
564 | * | ||
565 | * Determines the aspect ratio from the EDID. | ||
566 | * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2: | ||
567 | * "Horizontal and Vertical Screen Size or Aspect Ratio" | ||
568 | */ | ||
569 | struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait) | ||
570 | { | ||
571 | struct v4l2_fract aspect = { 16, 9 }; | ||
572 | u32 tmp; | ||
573 | u8 ratio; | ||
574 | |||
575 | /* Nothing filled in, fallback to 16:9 */ | ||
576 | if (!hor_landscape && !vert_portrait) | ||
577 | return aspect; | ||
578 | /* Both filled in, so they are interpreted as the screen size in cm */ | ||
579 | if (hor_landscape && vert_portrait) { | ||
580 | aspect.numerator = hor_landscape; | ||
581 | aspect.denominator = vert_portrait; | ||
582 | return aspect; | ||
583 | } | ||
584 | /* Only one is filled in, so interpret them as a ratio: | ||
585 | (val + 99) / 100 */ | ||
586 | ratio = hor_landscape | vert_portrait; | ||
587 | /* Change some rounded values into the exact aspect ratio */ | ||
588 | if (ratio == 79) { | ||
589 | aspect.numerator = 16; | ||
590 | aspect.denominator = 9; | ||
591 | } else if (ratio == 34) { | ||
592 | aspect.numerator = 4; | ||
593 | aspect.numerator = 3; | ||
594 | } else if (ratio == 68) { | ||
595 | aspect.numerator = 15; | ||
596 | aspect.numerator = 9; | ||
597 | } else { | ||
598 | aspect.numerator = hor_landscape + 99; | ||
599 | aspect.denominator = 100; | ||
600 | } | ||
601 | if (hor_landscape) | ||
602 | return aspect; | ||
603 | /* The aspect ratio is for portrait, so swap numerator and denominator */ | ||
604 | tmp = aspect.denominator; | ||
605 | aspect.denominator = aspect.numerator; | ||
606 | aspect.numerator = tmp; | ||
607 | return aspect; | ||
608 | } | ||
609 | EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio); | ||
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index e96497f7c3ed..7c4371288215 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | |||
@@ -196,6 +196,10 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) | |||
196 | * 2) at least one destination buffer has to be queued, | 196 | * 2) at least one destination buffer has to be queued, |
197 | * 3) streaming has to be on. | 197 | * 3) streaming has to be on. |
198 | * | 198 | * |
199 | * If a queue is buffered (for example a decoder hardware ringbuffer that has | ||
200 | * to be drained before doing streamoff), allow scheduling without v4l2 buffers | ||
201 | * on that queue. | ||
202 | * | ||
199 | * There may also be additional, custom requirements. In such case the driver | 203 | * There may also be additional, custom requirements. In such case the driver |
200 | * should supply a custom callback (job_ready in v4l2_m2m_ops) that should | 204 | * should supply a custom callback (job_ready in v4l2_m2m_ops) that should |
201 | * return 1 if the instance is ready. | 205 | * return 1 if the instance is ready. |
@@ -224,7 +228,8 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | |||
224 | } | 228 | } |
225 | 229 | ||
226 | spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); | 230 | spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); |
227 | if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) { | 231 | if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue) |
232 | && !m2m_ctx->out_q_ctx.buffered) { | ||
228 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, | 233 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, |
229 | flags_out); | 234 | flags_out); |
230 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | 235 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); |
@@ -232,7 +237,8 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | |||
232 | return; | 237 | return; |
233 | } | 238 | } |
234 | spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); | 239 | spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); |
235 | if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) { | 240 | if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue) |
241 | && !m2m_ctx->cap_q_ctx.buffered) { | ||
236 | spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, | 242 | spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, |
237 | flags_cap); | 243 | flags_cap); |
238 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, | 244 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, |
@@ -260,6 +266,39 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | |||
260 | } | 266 | } |
261 | 267 | ||
262 | /** | 268 | /** |
269 | * v4l2_m2m_cancel_job() - cancel pending jobs for the context | ||
270 | * | ||
271 | * In case of streamoff or release called on any context, | ||
272 | * 1] If the context is currently running, then abort job will be called | ||
273 | * 2] If the context is queued, then the context will be removed from | ||
274 | * the job_queue | ||
275 | */ | ||
276 | static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx) | ||
277 | { | ||
278 | struct v4l2_m2m_dev *m2m_dev; | ||
279 | unsigned long flags; | ||
280 | |||
281 | m2m_dev = m2m_ctx->m2m_dev; | ||
282 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||
283 | if (m2m_ctx->job_flags & TRANS_RUNNING) { | ||
284 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
285 | m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); | ||
286 | dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx); | ||
287 | wait_event(m2m_ctx->finished, | ||
288 | !(m2m_ctx->job_flags & TRANS_RUNNING)); | ||
289 | } else if (m2m_ctx->job_flags & TRANS_QUEUED) { | ||
290 | list_del(&m2m_ctx->queue); | ||
291 | m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); | ||
292 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
293 | dprintk("m2m_ctx: %p had been on queue and was removed\n", | ||
294 | m2m_ctx); | ||
295 | } else { | ||
296 | /* Do nothing, was not on queue/running */ | ||
297 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /** | ||
263 | * v4l2_m2m_job_finish() - inform the framework that a job has been finished | 302 | * v4l2_m2m_job_finish() - inform the framework that a job has been finished |
264 | * and have it clean up | 303 | * and have it clean up |
265 | * | 304 | * |
@@ -430,6 +469,9 @@ int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | |||
430 | unsigned long flags_job, flags; | 469 | unsigned long flags_job, flags; |
431 | int ret; | 470 | int ret; |
432 | 471 | ||
472 | /* wait until the current context is dequeued from job_queue */ | ||
473 | v4l2_m2m_cancel_job(m2m_ctx); | ||
474 | |||
433 | q_ctx = get_queue_ctx(m2m_ctx, type); | 475 | q_ctx = get_queue_ctx(m2m_ctx, type); |
434 | ret = vb2_streamoff(&q_ctx->q, type); | 476 | ret = vb2_streamoff(&q_ctx->q, type); |
435 | if (ret) | 477 | if (ret) |
@@ -652,27 +694,8 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init); | |||
652 | */ | 694 | */ |
653 | void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) | 695 | void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) |
654 | { | 696 | { |
655 | struct v4l2_m2m_dev *m2m_dev; | 697 | /* wait until the current context is dequeued from job_queue */ |
656 | unsigned long flags; | 698 | v4l2_m2m_cancel_job(m2m_ctx); |
657 | |||
658 | m2m_dev = m2m_ctx->m2m_dev; | ||
659 | |||
660 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||
661 | if (m2m_ctx->job_flags & TRANS_RUNNING) { | ||
662 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
663 | m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); | ||
664 | dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx); | ||
665 | wait_event(m2m_ctx->finished, !(m2m_ctx->job_flags & TRANS_RUNNING)); | ||
666 | } else if (m2m_ctx->job_flags & TRANS_QUEUED) { | ||
667 | list_del(&m2m_ctx->queue); | ||
668 | m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); | ||
669 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
670 | dprintk("m2m_ctx: %p had been on queue and was removed\n", | ||
671 | m2m_ctx); | ||
672 | } else { | ||
673 | /* Do nothing, was not on queue/running */ | ||
674 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
675 | } | ||
676 | 699 | ||
677 | vb2_queue_release(&m2m_ctx->cap_q_ctx.q); | 700 | vb2_queue_release(&m2m_ctx->cap_q_ctx.q); |
678 | vb2_queue_release(&m2m_ctx->out_q_ctx.q); | 701 | vb2_queue_release(&m2m_ctx->out_q_ctx.q); |
diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c index aa59639d013c..a6478dca0cde 100644 --- a/drivers/media/v4l2-core/v4l2-of.c +++ b/drivers/media/v4l2-core/v4l2-of.c | |||
@@ -100,6 +100,10 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node, | |||
100 | if (!of_property_read_u32(node, "data-shift", &v)) | 100 | if (!of_property_read_u32(node, "data-shift", &v)) |
101 | bus->data_shift = v; | 101 | bus->data_shift = v; |
102 | 102 | ||
103 | if (!of_property_read_u32(node, "sync-on-green-active", &v)) | ||
104 | flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : | ||
105 | V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; | ||
106 | |||
103 | bus->flags = flags; | 107 | bus->flags = flags; |
104 | 108 | ||
105 | } | 109 | } |
@@ -173,12 +177,8 @@ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent, | |||
173 | if (node) | 177 | if (node) |
174 | parent = node; | 178 | parent = node; |
175 | 179 | ||
176 | for_each_child_of_node(parent, node) { | 180 | port = of_get_child_by_name(parent, "port"); |
177 | if (!of_node_cmp(node->name, "port")) { | 181 | |
178 | port = node; | ||
179 | break; | ||
180 | } | ||
181 | } | ||
182 | if (port) { | 182 | if (port) { |
183 | /* Found a port, get an endpoint. */ | 183 | /* Found a port, get an endpoint. */ |
184 | endpoint = of_get_next_child(port, NULL); | 184 | endpoint = of_get_next_child(port, NULL); |
@@ -190,6 +190,7 @@ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent, | |||
190 | if (!endpoint) | 190 | if (!endpoint) |
191 | pr_err("%s(): no endpoint nodes specified for %s\n", | 191 | pr_err("%s(): no endpoint nodes specified for %s\n", |
192 | __func__, parent->full_name); | 192 | __func__, parent->full_name); |
193 | of_node_put(node); | ||
193 | } else { | 194 | } else { |
194 | port = of_get_parent(prev); | 195 | port = of_get_parent(prev); |
195 | if (!port) | 196 | if (!port) |
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 9fc4bab2da97..594c75eab5a5 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
@@ -334,6 +334,41 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer | |||
334 | } | 334 | } |
335 | 335 | ||
336 | /** | 336 | /** |
337 | * __verify_length() - Verify that the bytesused value for each plane fits in | ||
338 | * the plane length and that the data offset doesn't exceed the bytesused value. | ||
339 | */ | ||
340 | static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) | ||
341 | { | ||
342 | unsigned int length; | ||
343 | unsigned int plane; | ||
344 | |||
345 | if (!V4L2_TYPE_IS_OUTPUT(b->type)) | ||
346 | return 0; | ||
347 | |||
348 | if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { | ||
349 | for (plane = 0; plane < vb->num_planes; ++plane) { | ||
350 | length = (b->memory == V4L2_MEMORY_USERPTR) | ||
351 | ? b->m.planes[plane].length | ||
352 | : vb->v4l2_planes[plane].length; | ||
353 | |||
354 | if (b->m.planes[plane].bytesused > length) | ||
355 | return -EINVAL; | ||
356 | if (b->m.planes[plane].data_offset >= | ||
357 | b->m.planes[plane].bytesused) | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | } else { | ||
361 | length = (b->memory == V4L2_MEMORY_USERPTR) | ||
362 | ? b->length : vb->v4l2_planes[0].length; | ||
363 | |||
364 | if (b->bytesused > length) | ||
365 | return -EINVAL; | ||
366 | } | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | /** | ||
337 | * __buffer_in_use() - return true if the buffer is in use and | 372 | * __buffer_in_use() - return true if the buffer is in use and |
338 | * the queue cannot be freed (by the means of REQBUFS(0)) call | 373 | * the queue cannot be freed (by the means of REQBUFS(0)) call |
339 | */ | 374 | */ |
@@ -1167,6 +1202,10 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1167 | struct vb2_queue *q = vb->vb2_queue; | 1202 | struct vb2_queue *q = vb->vb2_queue; |
1168 | int ret; | 1203 | int ret; |
1169 | 1204 | ||
1205 | ret = __verify_length(vb, b); | ||
1206 | if (ret < 0) | ||
1207 | return ret; | ||
1208 | |||
1170 | switch (q->memory) { | 1209 | switch (q->memory) { |
1171 | case V4L2_MEMORY_MMAP: | 1210 | case V4L2_MEMORY_MMAP: |
1172 | ret = __qbuf_mmap(vb, b); | 1211 | ret = __qbuf_mmap(vb, b); |
@@ -1192,108 +1231,31 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1192 | return ret; | 1231 | return ret; |
1193 | } | 1232 | } |
1194 | 1233 | ||
1195 | /** | 1234 | static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, |
1196 | * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel | 1235 | const char *opname, |
1197 | * @q: videobuf2 queue | 1236 | int (*handler)(struct vb2_queue *, |
1198 | * @b: buffer structure passed from userspace to vidioc_prepare_buf | 1237 | struct v4l2_buffer *, |
1199 | * handler in driver | 1238 | struct vb2_buffer *)) |
1200 | * | ||
1201 | * Should be called from vidioc_prepare_buf ioctl handler of a driver. | ||
1202 | * This function: | ||
1203 | * 1) verifies the passed buffer, | ||
1204 | * 2) calls buf_prepare callback in the driver (if provided), in which | ||
1205 | * driver-specific buffer initialization can be performed, | ||
1206 | * | ||
1207 | * The return values from this function are intended to be directly returned | ||
1208 | * from vidioc_prepare_buf handler in driver. | ||
1209 | */ | ||
1210 | int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b) | ||
1211 | { | ||
1212 | struct vb2_buffer *vb; | ||
1213 | int ret; | ||
1214 | |||
1215 | if (q->fileio) { | ||
1216 | dprintk(1, "%s(): file io in progress\n", __func__); | ||
1217 | return -EBUSY; | ||
1218 | } | ||
1219 | |||
1220 | if (b->type != q->type) { | ||
1221 | dprintk(1, "%s(): invalid buffer type\n", __func__); | ||
1222 | return -EINVAL; | ||
1223 | } | ||
1224 | |||
1225 | if (b->index >= q->num_buffers) { | ||
1226 | dprintk(1, "%s(): buffer index out of range\n", __func__); | ||
1227 | return -EINVAL; | ||
1228 | } | ||
1229 | |||
1230 | vb = q->bufs[b->index]; | ||
1231 | if (NULL == vb) { | ||
1232 | /* Should never happen */ | ||
1233 | dprintk(1, "%s(): buffer is NULL\n", __func__); | ||
1234 | return -EINVAL; | ||
1235 | } | ||
1236 | |||
1237 | if (b->memory != q->memory) { | ||
1238 | dprintk(1, "%s(): invalid memory type\n", __func__); | ||
1239 | return -EINVAL; | ||
1240 | } | ||
1241 | |||
1242 | if (vb->state != VB2_BUF_STATE_DEQUEUED) { | ||
1243 | dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state); | ||
1244 | return -EINVAL; | ||
1245 | } | ||
1246 | ret = __verify_planes_array(vb, b); | ||
1247 | if (ret < 0) | ||
1248 | return ret; | ||
1249 | ret = __buf_prepare(vb, b); | ||
1250 | if (ret < 0) | ||
1251 | return ret; | ||
1252 | |||
1253 | __fill_v4l2_buffer(vb, b); | ||
1254 | |||
1255 | return 0; | ||
1256 | } | ||
1257 | EXPORT_SYMBOL_GPL(vb2_prepare_buf); | ||
1258 | |||
1259 | /** | ||
1260 | * vb2_qbuf() - Queue a buffer from userspace | ||
1261 | * @q: videobuf2 queue | ||
1262 | * @b: buffer structure passed from userspace to vidioc_qbuf handler | ||
1263 | * in driver | ||
1264 | * | ||
1265 | * Should be called from vidioc_qbuf ioctl handler of a driver. | ||
1266 | * This function: | ||
1267 | * 1) verifies the passed buffer, | ||
1268 | * 2) if necessary, calls buf_prepare callback in the driver (if provided), in | ||
1269 | * which driver-specific buffer initialization can be performed, | ||
1270 | * 3) if streaming is on, queues the buffer in driver by the means of buf_queue | ||
1271 | * callback for processing. | ||
1272 | * | ||
1273 | * The return values from this function are intended to be directly returned | ||
1274 | * from vidioc_qbuf handler in driver. | ||
1275 | */ | ||
1276 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | ||
1277 | { | 1239 | { |
1278 | struct rw_semaphore *mmap_sem = NULL; | 1240 | struct rw_semaphore *mmap_sem = NULL; |
1279 | struct vb2_buffer *vb; | 1241 | struct vb2_buffer *vb; |
1280 | int ret = 0; | 1242 | int ret; |
1281 | 1243 | ||
1282 | /* | 1244 | /* |
1283 | * In case of user pointer buffers vb2 allocator needs to get direct | 1245 | * In case of user pointer buffers vb2 allocators need to get direct |
1284 | * access to userspace pages. This requires getting read access on | 1246 | * access to userspace pages. This requires getting the mmap semaphore |
1285 | * mmap semaphore in the current process structure. The same | 1247 | * for read access in the current process structure. The same semaphore |
1286 | * semaphore is taken before calling mmap operation, while both mmap | 1248 | * is taken before calling mmap operation, while both qbuf/prepare_buf |
1287 | * and qbuf are called by the driver or v4l2 core with driver's lock | 1249 | * and mmap are called by the driver or v4l2 core with the driver's lock |
1288 | * held. To avoid a AB-BA deadlock (mmap_sem then driver's lock in | 1250 | * held. To avoid an AB-BA deadlock (mmap_sem then driver's lock in mmap |
1289 | * mmap and driver's lock then mmap_sem in qbuf) the videobuf2 core | 1251 | * and driver's lock then mmap_sem in qbuf/prepare_buf) the videobuf2 |
1290 | * release driver's lock, takes mmap_sem and then takes again driver's | 1252 | * core releases the driver's lock, takes mmap_sem and then takes the |
1291 | * lock. | 1253 | * driver's lock again. |
1292 | * | 1254 | * |
1293 | * To avoid race with other vb2 calls, which might be called after | 1255 | * To avoid racing with other vb2 calls, which might be called after |
1294 | * releasing driver's lock, this operation is performed at the | 1256 | * releasing the driver's lock, this operation is performed at the |
1295 | * beggining of qbuf processing. This way the queue status is | 1257 | * beginning of qbuf/prepare_buf processing. This way the queue status |
1296 | * consistent after getting driver's lock back. | 1258 | * is consistent after getting the driver's lock back. |
1297 | */ | 1259 | */ |
1298 | if (q->memory == V4L2_MEMORY_USERPTR) { | 1260 | if (q->memory == V4L2_MEMORY_USERPTR) { |
1299 | mmap_sem = ¤t->mm->mmap_sem; | 1261 | mmap_sem = ¤t->mm->mmap_sem; |
@@ -1303,19 +1265,19 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
1303 | } | 1265 | } |
1304 | 1266 | ||
1305 | if (q->fileio) { | 1267 | if (q->fileio) { |
1306 | dprintk(1, "qbuf: file io in progress\n"); | 1268 | dprintk(1, "%s(): file io in progress\n", opname); |
1307 | ret = -EBUSY; | 1269 | ret = -EBUSY; |
1308 | goto unlock; | 1270 | goto unlock; |
1309 | } | 1271 | } |
1310 | 1272 | ||
1311 | if (b->type != q->type) { | 1273 | if (b->type != q->type) { |
1312 | dprintk(1, "qbuf: invalid buffer type\n"); | 1274 | dprintk(1, "%s(): invalid buffer type\n", opname); |
1313 | ret = -EINVAL; | 1275 | ret = -EINVAL; |
1314 | goto unlock; | 1276 | goto unlock; |
1315 | } | 1277 | } |
1316 | 1278 | ||
1317 | if (b->index >= q->num_buffers) { | 1279 | if (b->index >= q->num_buffers) { |
1318 | dprintk(1, "qbuf: buffer index out of range\n"); | 1280 | dprintk(1, "%s(): buffer index out of range\n", opname); |
1319 | ret = -EINVAL; | 1281 | ret = -EINVAL; |
1320 | goto unlock; | 1282 | goto unlock; |
1321 | } | 1283 | } |
@@ -1323,31 +1285,83 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
1323 | vb = q->bufs[b->index]; | 1285 | vb = q->bufs[b->index]; |
1324 | if (NULL == vb) { | 1286 | if (NULL == vb) { |
1325 | /* Should never happen */ | 1287 | /* Should never happen */ |
1326 | dprintk(1, "qbuf: buffer is NULL\n"); | 1288 | dprintk(1, "%s(): buffer is NULL\n", opname); |
1327 | ret = -EINVAL; | 1289 | ret = -EINVAL; |
1328 | goto unlock; | 1290 | goto unlock; |
1329 | } | 1291 | } |
1330 | 1292 | ||
1331 | if (b->memory != q->memory) { | 1293 | if (b->memory != q->memory) { |
1332 | dprintk(1, "qbuf: invalid memory type\n"); | 1294 | dprintk(1, "%s(): invalid memory type\n", opname); |
1333 | ret = -EINVAL; | 1295 | ret = -EINVAL; |
1334 | goto unlock; | 1296 | goto unlock; |
1335 | } | 1297 | } |
1298 | |||
1336 | ret = __verify_planes_array(vb, b); | 1299 | ret = __verify_planes_array(vb, b); |
1337 | if (ret) | 1300 | if (ret) |
1338 | goto unlock; | 1301 | goto unlock; |
1339 | 1302 | ||
1303 | ret = handler(q, b, vb); | ||
1304 | if (ret) | ||
1305 | goto unlock; | ||
1306 | |||
1307 | /* Fill buffer information for the userspace */ | ||
1308 | __fill_v4l2_buffer(vb, b); | ||
1309 | |||
1310 | dprintk(1, "%s() of buffer %d succeeded\n", opname, vb->v4l2_buf.index); | ||
1311 | unlock: | ||
1312 | if (mmap_sem) | ||
1313 | up_read(mmap_sem); | ||
1314 | return ret; | ||
1315 | } | ||
1316 | |||
1317 | static int __vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, | ||
1318 | struct vb2_buffer *vb) | ||
1319 | { | ||
1320 | if (vb->state != VB2_BUF_STATE_DEQUEUED) { | ||
1321 | dprintk(1, "%s(): invalid buffer state %d\n", __func__, | ||
1322 | vb->state); | ||
1323 | return -EINVAL; | ||
1324 | } | ||
1325 | |||
1326 | return __buf_prepare(vb, b); | ||
1327 | } | ||
1328 | |||
1329 | /** | ||
1330 | * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel | ||
1331 | * @q: videobuf2 queue | ||
1332 | * @b: buffer structure passed from userspace to vidioc_prepare_buf | ||
1333 | * handler in driver | ||
1334 | * | ||
1335 | * Should be called from vidioc_prepare_buf ioctl handler of a driver. | ||
1336 | * This function: | ||
1337 | * 1) verifies the passed buffer, | ||
1338 | * 2) calls buf_prepare callback in the driver (if provided), in which | ||
1339 | * driver-specific buffer initialization can be performed, | ||
1340 | * | ||
1341 | * The return values from this function are intended to be directly returned | ||
1342 | * from vidioc_prepare_buf handler in driver. | ||
1343 | */ | ||
1344 | int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b) | ||
1345 | { | ||
1346 | return vb2_queue_or_prepare_buf(q, b, "prepare_buf", __vb2_prepare_buf); | ||
1347 | } | ||
1348 | EXPORT_SYMBOL_GPL(vb2_prepare_buf); | ||
1349 | |||
1350 | static int __vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b, | ||
1351 | struct vb2_buffer *vb) | ||
1352 | { | ||
1353 | int ret; | ||
1354 | |||
1340 | switch (vb->state) { | 1355 | switch (vb->state) { |
1341 | case VB2_BUF_STATE_DEQUEUED: | 1356 | case VB2_BUF_STATE_DEQUEUED: |
1342 | ret = __buf_prepare(vb, b); | 1357 | ret = __buf_prepare(vb, b); |
1343 | if (ret) | 1358 | if (ret) |
1344 | goto unlock; | 1359 | return ret; |
1345 | case VB2_BUF_STATE_PREPARED: | 1360 | case VB2_BUF_STATE_PREPARED: |
1346 | break; | 1361 | break; |
1347 | default: | 1362 | default: |
1348 | dprintk(1, "qbuf: buffer already in use\n"); | 1363 | dprintk(1, "qbuf: buffer already in use\n"); |
1349 | ret = -EINVAL; | 1364 | return -EINVAL; |
1350 | goto unlock; | ||
1351 | } | 1365 | } |
1352 | 1366 | ||
1353 | /* | 1367 | /* |
@@ -1364,14 +1378,29 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
1364 | if (q->streaming) | 1378 | if (q->streaming) |
1365 | __enqueue_in_driver(vb); | 1379 | __enqueue_in_driver(vb); |
1366 | 1380 | ||
1367 | /* Fill buffer information for the userspace */ | 1381 | return 0; |
1368 | __fill_v4l2_buffer(vb, b); | 1382 | } |
1369 | 1383 | ||
1370 | dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index); | 1384 | /** |
1371 | unlock: | 1385 | * vb2_qbuf() - Queue a buffer from userspace |
1372 | if (mmap_sem) | 1386 | * @q: videobuf2 queue |
1373 | up_read(mmap_sem); | 1387 | * @b: buffer structure passed from userspace to vidioc_qbuf handler |
1374 | return ret; | 1388 | * in driver |
1389 | * | ||
1390 | * Should be called from vidioc_qbuf ioctl handler of a driver. | ||
1391 | * This function: | ||
1392 | * 1) verifies the passed buffer, | ||
1393 | * 2) if necessary, calls buf_prepare callback in the driver (if provided), in | ||
1394 | * which driver-specific buffer initialization can be performed, | ||
1395 | * 3) if streaming is on, queues the buffer in driver by the means of buf_queue | ||
1396 | * callback for processing. | ||
1397 | * | ||
1398 | * The return values from this function are intended to be directly returned | ||
1399 | * from vidioc_qbuf handler in driver. | ||
1400 | */ | ||
1401 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | ||
1402 | { | ||
1403 | return vb2_queue_or_prepare_buf(q, b, "qbuf", __vb2_qbuf); | ||
1375 | } | 1404 | } |
1376 | EXPORT_SYMBOL_GPL(vb2_qbuf); | 1405 | EXPORT_SYMBOL_GPL(vb2_qbuf); |
1377 | 1406 | ||
@@ -2578,8 +2607,15 @@ EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf); | |||
2578 | int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) | 2607 | int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) |
2579 | { | 2608 | { |
2580 | struct video_device *vdev = video_devdata(file); | 2609 | struct video_device *vdev = video_devdata(file); |
2610 | struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; | ||
2611 | int err; | ||
2581 | 2612 | ||
2582 | return vb2_mmap(vdev->queue, vma); | 2613 | if (lock && mutex_lock_interruptible(lock)) |
2614 | return -ERESTARTSYS; | ||
2615 | err = vb2_mmap(vdev->queue, vma); | ||
2616 | if (lock) | ||
2617 | mutex_unlock(lock); | ||
2618 | return err; | ||
2583 | } | 2619 | } |
2584 | EXPORT_SYMBOL_GPL(vb2_fop_mmap); | 2620 | EXPORT_SYMBOL_GPL(vb2_fop_mmap); |
2585 | 2621 | ||
@@ -2685,8 +2721,15 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, | |||
2685 | unsigned long len, unsigned long pgoff, unsigned long flags) | 2721 | unsigned long len, unsigned long pgoff, unsigned long flags) |
2686 | { | 2722 | { |
2687 | struct video_device *vdev = video_devdata(file); | 2723 | struct video_device *vdev = video_devdata(file); |
2724 | struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; | ||
2725 | int ret; | ||
2688 | 2726 | ||
2689 | return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); | 2727 | if (lock && mutex_lock_interruptible(lock)) |
2728 | return -ERESTARTSYS; | ||
2729 | ret = vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); | ||
2730 | if (lock) | ||
2731 | mutex_unlock(lock); | ||
2732 | return ret; | ||
2690 | } | 2733 | } |
2691 | EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); | 2734 | EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); |
2692 | #endif | 2735 | #endif |