Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6:
[media] v1.88 DM04/QQBOX Move remote to use rc_core dvb-usb-remote
[media] Add missing include guard to header file
[media] Inlined functions should be static
[media] Remove invalid parameter description
[media] cpia2: fix warning about invalid trigraph sequence
[media] s5p-csis: Add missing dependency on PLAT_S5P
[media] gspca/kinect: wrap gspca_debug with GSPCA_DEBUG
[media] fintek-cir: new driver for Fintek LPC SuperIO CIR function
[media] uvcvideo: Connect video devices to media entities
[media] uvcvideo: Register subdevices for each entity
[media] uvcvideo: Register a v4l2_device
[media] add V4L2-PIX-FMT-SRGGB12 & friends to docbook
[media] Documentation/DocBook: Rename media fops xml files
[media] Media DocBook: fix validation errors
[media] wl12xx: g_volatile_ctrl fix: wrong field set
[media] fix kconfig dependency warning for VIDEO_TIMBERDALE
[media] dm1105: GPIO handling added, I2C on GPIO added, LNB control through GPIO reworked
[media] Add support for M-5MOLS 8 Mega Pixel camera ISP

+3750 -195
+4 -1
Documentation/DocBook/dvb/dvbproperty.xml
··· 141 141 </row></tbody></tgroup></informaltable> 142 142 </section> 143 143 144 + <section> 145 + <title>Property types</title> 144 146 <para> 145 147 On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>, 146 148 the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to 147 149 get/set up to 64 properties. The actual meaning of each property is described on the next sections. 148 150 </para> 149 151 150 - <para>The Available frontend property types are:</para> 152 + <para>The available frontend property types are:</para> 151 153 <programlisting> 152 154 #define DTV_UNDEFINED 0 153 155 #define DTV_TUNE 1 ··· 195 193 #define DTV_ISDBT_LAYER_ENABLED 41 196 194 #define DTV_ISDBS_TS_ID 42 197 195 </programlisting> 196 + </section> 198 197 199 198 <section id="fe_property_common"> 200 199 <title>Parameters that are common to all Digital TV standards</title>
+4 -3
Documentation/DocBook/media-entities.tmpl
··· 293 293 <!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml"> 294 294 <!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml"> 295 295 <!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml"> 296 + <!ENTITY sub-srggb12 SYSTEM "v4l/pixfmt-srggb12.xml"> 296 297 <!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml"> 297 298 <!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml"> 298 299 <!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml"> ··· 374 373 <!ENTITY sub-media-indices SYSTEM "media-indices.tmpl"> 375 374 376 375 <!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml"> 377 - <!ENTITY sub-media-open SYSTEM "v4l/media-func-open.xml"> 378 - <!ENTITY sub-media-close SYSTEM "v4l/media-func-close.xml"> 379 - <!ENTITY sub-media-ioctl SYSTEM "v4l/media-func-ioctl.xml"> 376 + <!ENTITY sub-media-func-open SYSTEM "v4l/media-func-open.xml"> 377 + <!ENTITY sub-media-func-close SYSTEM "v4l/media-func-close.xml"> 378 + <!ENTITY sub-media-func-ioctl SYSTEM "v4l/media-func-ioctl.xml"> 380 379 <!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml"> 381 380 <!ENTITY sub-media-ioc-enum-entities SYSTEM "v4l/media-ioc-enum-entities.xml"> 382 381 <!ENTITY sub-media-ioc-enum-links SYSTEM "v4l/media-ioc-enum-links.xml">
+3 -3
Documentation/DocBook/v4l/media-controller.xml
··· 78 78 <appendix id="media-user-func"> 79 79 <title>Function Reference</title> 80 80 <!-- Keep this alphabetically sorted. --> 81 - &sub-media-open; 82 - &sub-media-close; 83 - &sub-media-ioctl; 81 + &sub-media-func-open; 82 + &sub-media-func-close; 83 + &sub-media-func-ioctl; 84 84 <!-- All ioctls go here. --> 85 85 &sub-media-ioc-device-info; 86 86 &sub-media-ioc-enum-entities;
+1
Documentation/DocBook/v4l/pixfmt.xml
··· 673 673 &sub-srggb8; 674 674 &sub-sbggr16; 675 675 &sub-srggb10; 676 + &sub-srggb12; 676 677 </section> 677 678 678 679 <section id="yuv-formats">
+5 -5
Documentation/DocBook/v4l/subdev-formats.xml
··· 2531 2531 <constant>_JPEG</constant> prefix the format code is made of 2532 2532 the following information. 2533 2533 <itemizedlist> 2534 - <listitem>The number of bus samples per entropy encoded byte.</listitem> 2535 - <listitem>The bus width.</listitem> 2534 + <listitem><para>The number of bus samples per entropy encoded byte.</para></listitem> 2535 + <listitem><para>The bus width.</para></listitem> 2536 2536 </itemizedlist> 2537 + </para> 2537 2538 2538 - <para>For instance, for a JPEG baseline process and an 8-bit bus width 2539 - the format will be named <constant>V4L2_MBUS_FMT_JPEG_1X8</constant>. 2540 - </para> 2539 + <para>For instance, for a JPEG baseline process and an 8-bit bus width 2540 + the format will be named <constant>V4L2_MBUS_FMT_JPEG_1X8</constant>. 2541 2541 </para> 2542 2542 2543 2543 <para>The following table lists existing JPEG compressed formats.</para>
+236 -36
drivers/media/dvb/dm1105/dm1105.c
··· 20 20 */ 21 21 22 22 #include <linux/i2c.h> 23 + #include <linux/i2c-algo-bit.h> 23 24 #include <linux/init.h> 24 25 #include <linux/kernel.h> 25 26 #include <linux/module.h> ··· 50 49 51 50 #define UNSET (-1U) 52 51 53 - #define DM1105_BOARD_NOAUTO UNSET 54 - #define DM1105_BOARD_UNKNOWN 0 55 - #define DM1105_BOARD_DVBWORLD_2002 1 56 - #define DM1105_BOARD_DVBWORLD_2004 2 57 - #define DM1105_BOARD_AXESS_DM05 3 52 + #define DM1105_BOARD_NOAUTO UNSET 53 + #define DM1105_BOARD_UNKNOWN 0 54 + #define DM1105_BOARD_DVBWORLD_2002 1 55 + #define DM1105_BOARD_DVBWORLD_2004 2 56 + #define DM1105_BOARD_AXESS_DM05 3 57 + #define DM1105_BOARD_UNBRANDED_I2C_ON_GPIO 4 58 58 59 59 /* ----------------------------------------------- */ 60 60 /* ··· 159 157 #define DM1105_MAX 0x04 160 158 161 159 #define DRIVER_NAME "dm1105" 160 + #define DM1105_I2C_GPIO_NAME "dm1105-gpio" 162 161 163 162 #define DM1105_DMA_PACKETS 47 164 163 #define DM1105_DMA_PACKET_LENGTH (128*4) 165 164 #define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) 166 165 166 + /* */ 167 + #define GPIO08 (1 << 8) 168 + #define GPIO13 (1 << 13) 169 + #define GPIO14 (1 << 14) 170 + #define GPIO15 (1 << 15) 171 + #define GPIO16 (1 << 16) 172 + #define GPIO17 (1 << 17) 173 + #define GPIO_ALL 0x03ffff 174 + 167 175 /* GPIO's for LNB power control */ 168 - #define DM1105_LNB_MASK 0x00000000 169 - #define DM1105_LNB_OFF 0x00020000 170 - #define DM1105_LNB_13V 0x00010100 171 - #define DM1105_LNB_18V 0x00000100 176 + #define DM1105_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) 177 + #define DM1105_LNB_OFF GPIO17 178 + #define DM1105_LNB_13V (GPIO16 | GPIO08) 179 + #define DM1105_LNB_18V GPIO08 172 180 173 181 /* GPIO's for LNB power control for Axess DM05 */ 174 - #define DM05_LNB_MASK 0x00000000 175 - #define DM05_LNB_OFF 0x00020000/* actually 13v */ 176 - #define DM05_LNB_13V 0x00020000 177 - #define DM05_LNB_18V 0x00030000 182 + #define DM05_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) 183 + #define DM05_LNB_OFF GPIO17/* actually 13v */ 184 + #define DM05_LNB_13V GPIO17 185 + #define DM05_LNB_18V (GPIO17 | GPIO16) 186 + 187 + /* GPIO's for LNB power control for unbranded with I2C on GPIO */ 188 + #define UNBR_LNB_MASK (GPIO17 | GPIO16) 189 + #define UNBR_LNB_OFF 0 190 + #define UNBR_LNB_13V GPIO17 191 + #define UNBR_LNB_18V (GPIO17 | GPIO16) 178 192 179 193 static unsigned int card[] = {[0 ... 3] = UNSET }; 180 194 module_param_array(card, int, NULL, 0444); ··· 205 187 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 206 188 207 189 struct dm1105_board { 208 - char *name; 190 + char *name; 191 + struct { 192 + u32 mask, off, v13, v18; 193 + } lnb; 194 + u32 gpio_scl, gpio_sda; 209 195 }; 210 196 211 197 struct dm1105_subid { ··· 221 199 static const struct dm1105_board dm1105_boards[] = { 222 200 [DM1105_BOARD_UNKNOWN] = { 223 201 .name = "UNKNOWN/GENERIC", 202 + .lnb = { 203 + .mask = DM1105_LNB_MASK, 204 + .off = DM1105_LNB_OFF, 205 + .v13 = DM1105_LNB_13V, 206 + .v18 = DM1105_LNB_18V, 207 + }, 224 208 }, 225 209 [DM1105_BOARD_DVBWORLD_2002] = { 226 210 .name = "DVBWorld PCI 2002", 211 + .lnb = { 212 + .mask = DM1105_LNB_MASK, 213 + .off = DM1105_LNB_OFF, 214 + .v13 = DM1105_LNB_13V, 215 + .v18 = DM1105_LNB_18V, 216 + }, 227 217 }, 228 218 [DM1105_BOARD_DVBWORLD_2004] = { 229 219 .name = "DVBWorld PCI 2004", 220 + .lnb = { 221 + .mask = DM1105_LNB_MASK, 222 + .off = DM1105_LNB_OFF, 223 + .v13 = DM1105_LNB_13V, 224 + .v18 = DM1105_LNB_18V, 225 + }, 230 226 }, 231 227 [DM1105_BOARD_AXESS_DM05] = { 232 228 .name = "Axess/EasyTv DM05", 229 + .lnb = { 230 + .mask = DM05_LNB_MASK, 231 + .off = DM05_LNB_OFF, 232 + .v13 = DM05_LNB_13V, 233 + .v18 = DM05_LNB_18V, 234 + }, 235 + }, 236 + [DM1105_BOARD_UNBRANDED_I2C_ON_GPIO] = { 237 + .name = "Unbranded DM1105 with i2c on GPIOs", 238 + .lnb = { 239 + .mask = UNBR_LNB_MASK, 240 + .off = UNBR_LNB_OFF, 241 + .v13 = UNBR_LNB_13V, 242 + .v18 = UNBR_LNB_18V, 243 + }, 244 + .gpio_scl = GPIO14, 245 + .gpio_sda = GPIO13, 233 246 }, 234 247 }; 235 248 ··· 350 293 351 294 /* i2c */ 352 295 struct i2c_adapter i2c_adap; 296 + struct i2c_adapter i2c_bb_adap; 297 + struct i2c_algo_bit_data i2c_bit; 353 298 354 299 /* irq */ 355 300 struct work_struct work; ··· 386 327 387 328 #define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) 388 329 #define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) 330 + 331 + /* The chip has 18 GPIOs. In HOST mode GPIO's used as 15 bit address lines, 332 + so we can use only 3 GPIO's from GPIO15 to GPIO17. 333 + Here I don't check whether HOST is enebled as it is not implemented yet. 334 + */ 335 + static void dm1105_gpio_set(struct dm1105_dev *dev, u32 mask) 336 + { 337 + if (mask & 0xfffc0000) 338 + printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 339 + 340 + if (mask & 0x0003ffff) 341 + dm_setl(DM1105_GPIOVAL, mask & 0x0003ffff); 342 + 343 + } 344 + 345 + static void dm1105_gpio_clear(struct dm1105_dev *dev, u32 mask) 346 + { 347 + if (mask & 0xfffc0000) 348 + printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 349 + 350 + if (mask & 0x0003ffff) 351 + dm_clearl(DM1105_GPIOVAL, mask & 0x0003ffff); 352 + 353 + } 354 + 355 + static void dm1105_gpio_andor(struct dm1105_dev *dev, u32 mask, u32 val) 356 + { 357 + if (mask & 0xfffc0000) 358 + printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 359 + 360 + if (mask & 0x0003ffff) 361 + dm_andorl(DM1105_GPIOVAL, mask & 0x0003ffff, val); 362 + 363 + } 364 + 365 + static u32 dm1105_gpio_get(struct dm1105_dev *dev, u32 mask) 366 + { 367 + if (mask & 0xfffc0000) 368 + printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 369 + 370 + if (mask & 0x0003ffff) 371 + return dm_readl(DM1105_GPIOVAL) & mask & 0x0003ffff; 372 + 373 + return 0; 374 + } 375 + 376 + static void dm1105_gpio_enable(struct dm1105_dev *dev, u32 mask, int asoutput) 377 + { 378 + if (mask & 0xfffc0000) 379 + printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 380 + 381 + if ((mask & 0x0003ffff) && asoutput) 382 + dm_clearl(DM1105_GPIOCTR, mask & 0x0003ffff); 383 + else if ((mask & 0x0003ffff) && !asoutput) 384 + dm_setl(DM1105_GPIOCTR, mask & 0x0003ffff); 385 + 386 + } 387 + 388 + static void dm1105_setline(struct dm1105_dev *dev, u32 line, int state) 389 + { 390 + if (state) 391 + dm1105_gpio_enable(dev, line, 0); 392 + else { 393 + dm1105_gpio_enable(dev, line, 1); 394 + dm1105_gpio_clear(dev, line); 395 + } 396 + } 397 + 398 + static void dm1105_setsda(void *data, int state) 399 + { 400 + struct dm1105_dev *dev = data; 401 + 402 + dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_sda, state); 403 + } 404 + 405 + static void dm1105_setscl(void *data, int state) 406 + { 407 + struct dm1105_dev *dev = data; 408 + 409 + dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_scl, state); 410 + } 411 + 412 + static int dm1105_getsda(void *data) 413 + { 414 + struct dm1105_dev *dev = data; 415 + 416 + return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_sda) 417 + ? 1 : 0; 418 + } 419 + 420 + static int dm1105_getscl(void *data) 421 + { 422 + struct dm1105_dev *dev = data; 423 + 424 + return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_scl) 425 + ? 1 : 0; 426 + } 389 427 390 428 static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, 391 429 struct i2c_msg *msgs, int num) ··· 592 436 static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) 593 437 { 594 438 struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); 595 - u32 lnb_mask, lnb_13v, lnb_18v, lnb_off; 596 439 597 - switch (dev->boardnr) { 598 - case DM1105_BOARD_AXESS_DM05: 599 - lnb_mask = DM05_LNB_MASK; 600 - lnb_off = DM05_LNB_OFF; 601 - lnb_13v = DM05_LNB_13V; 602 - lnb_18v = DM05_LNB_18V; 603 - break; 604 - case DM1105_BOARD_DVBWORLD_2002: 605 - case DM1105_BOARD_DVBWORLD_2004: 606 - default: 607 - lnb_mask = DM1105_LNB_MASK; 608 - lnb_off = DM1105_LNB_OFF; 609 - lnb_13v = DM1105_LNB_13V; 610 - lnb_18v = DM1105_LNB_18V; 611 - } 612 - 613 - dm_writel(DM1105_GPIOCTR, lnb_mask); 440 + dm1105_gpio_enable(dev, dm1105_boards[dev->boardnr].lnb.mask, 1); 614 441 if (voltage == SEC_VOLTAGE_18) 615 - dm_writel(DM1105_GPIOVAL, lnb_18v); 442 + dm1105_gpio_andor(dev, 443 + dm1105_boards[dev->boardnr].lnb.mask, 444 + dm1105_boards[dev->boardnr].lnb.v18); 616 445 else if (voltage == SEC_VOLTAGE_13) 617 - dm_writel(DM1105_GPIOVAL, lnb_13v); 446 + dm1105_gpio_andor(dev, 447 + dm1105_boards[dev->boardnr].lnb.mask, 448 + dm1105_boards[dev->boardnr].lnb.v13); 618 449 else 619 - dm_writel(DM1105_GPIOVAL, lnb_off); 450 + dm1105_gpio_andor(dev, 451 + dm1105_boards[dev->boardnr].lnb.mask, 452 + dm1105_boards[dev->boardnr].lnb.off); 620 453 621 454 return 0; 622 455 } ··· 853 708 int ret; 854 709 855 710 switch (dev->boardnr) { 711 + case DM1105_BOARD_UNBRANDED_I2C_ON_GPIO: 712 + dm1105_gpio_enable(dev, GPIO15, 1); 713 + dm1105_gpio_clear(dev, GPIO15); 714 + msleep(100); 715 + dm1105_gpio_set(dev, GPIO15); 716 + msleep(200); 717 + dev->fe = dvb_attach( 718 + stv0299_attach, &sharp_z0194a_config, 719 + &dev->i2c_bb_adap); 720 + if (dev->fe) { 721 + dev->fe->ops.set_voltage = dm1105_set_voltage; 722 + dvb_attach(dvb_pll_attach, dev->fe, 0x60, 723 + &dev->i2c_bb_adap, DVB_PLL_OPERA1); 724 + break; 725 + } 726 + 727 + dev->fe = dvb_attach( 728 + stv0288_attach, &earda_config, 729 + &dev->i2c_bb_adap); 730 + if (dev->fe) { 731 + dev->fe->ops.set_voltage = dm1105_set_voltage; 732 + dvb_attach(stb6000_attach, dev->fe, 0x61, 733 + &dev->i2c_bb_adap); 734 + break; 735 + } 736 + 737 + dev->fe = dvb_attach( 738 + si21xx_attach, &serit_config, 739 + &dev->i2c_bb_adap); 740 + if (dev->fe) 741 + dev->fe->ops.set_voltage = dm1105_set_voltage; 742 + break; 856 743 case DM1105_BOARD_DVBWORLD_2004: 857 744 dev->fe = dvb_attach( 858 745 cx24116_attach, &serit_sp2633_config, ··· 1047 870 if (ret < 0) 1048 871 goto err_dm1105_hw_exit; 1049 872 873 + i2c_set_adapdata(&dev->i2c_bb_adap, dev); 874 + strcpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME); 875 + dev->i2c_bb_adap.owner = THIS_MODULE; 876 + dev->i2c_bb_adap.dev.parent = &pdev->dev; 877 + dev->i2c_bb_adap.algo_data = &dev->i2c_bit; 878 + dev->i2c_bit.data = dev; 879 + dev->i2c_bit.setsda = dm1105_setsda; 880 + dev->i2c_bit.setscl = dm1105_setscl; 881 + dev->i2c_bit.getsda = dm1105_getsda; 882 + dev->i2c_bit.getscl = dm1105_getscl; 883 + dev->i2c_bit.udelay = 10; 884 + dev->i2c_bit.timeout = 10; 885 + 886 + /* Raise SCL and SDA */ 887 + dm1105_setsda(dev, 1); 888 + dm1105_setscl(dev, 1); 889 + 890 + ret = i2c_bit_add_bus(&dev->i2c_bb_adap); 891 + if (ret < 0) 892 + goto err_i2c_del_adapter; 893 + 1050 894 /* dvb */ 1051 895 ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, 1052 896 THIS_MODULE, &pdev->dev, adapter_nr); 1053 897 if (ret < 0) 1054 - goto err_i2c_del_adapter; 898 + goto err_i2c_del_adapters; 1055 899 1056 900 dvb_adapter = &dev->dvb_adapter; 1057 901 ··· 1150 952 dvb_dmx_release(dvbdemux); 1151 953 err_dvb_unregister_adapter: 1152 954 dvb_unregister_adapter(dvb_adapter); 955 + err_i2c_del_adapters: 956 + i2c_del_adapter(&dev->i2c_bb_adap); 1153 957 err_i2c_del_adapter: 1154 958 i2c_del_adapter(&dev->i2c_adap); 1155 959 err_dm1105_hw_exit:
+43 -64
drivers/media/dvb/dvb-usb/lmedm04.c
··· 207 207 rbuff, sizeof(rbuff)); 208 208 return ret; 209 209 } 210 - static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress) 211 - { 212 - struct dvb_usb_device *d = adap->dev; 213 - 214 - deb_info(1, "INT Key Keypress =%04x", keypress); 215 - 216 - if (keypress > 0) 217 - rc_keydown(d->rc_dev, keypress, 0); 218 - 219 - return 0; 220 - } 221 210 222 211 static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) 223 212 { ··· 245 256 struct lme2510_state *st = adap->dev->priv; 246 257 static u8 *ibuf, *rbuf; 247 258 int i = 0, offset; 259 + u32 key; 248 260 249 261 switch (lme_urb->status) { 250 262 case 0: ··· 272 282 273 283 switch (ibuf[0]) { 274 284 case 0xaa: 275 - debug_data_snipet(1, "INT Remote data snipet in", ibuf); 276 - lme2510_remote_keypress(adap, 277 - (u32)(ibuf[2] << 24) + (ibuf[3] << 16) + 278 - (ibuf[4] << 8) + ibuf[5]); 285 + debug_data_snipet(1, "INT Remote data snipet", ibuf); 286 + if ((ibuf[4] + ibuf[5]) == 0xff) { 287 + key = ibuf[5]; 288 + key += (ibuf[3] > 0) 289 + ? (ibuf[3] ^ 0xff) << 8 : 0; 290 + key += (ibuf[2] ^ 0xff) << 16; 291 + deb_info(1, "INT Key =%08x", key); 292 + if (adap->dev->rc_dev != NULL) 293 + rc_keydown(adap->dev->rc_dev, key, 0); 294 + } 279 295 break; 280 296 case 0xbb: 281 297 switch (st->tuner_config) { ··· 687 691 return (ret < 0) ? -ENODEV : 0; 688 692 } 689 693 690 - static int lme2510_int_service(struct dvb_usb_adapter *adap) 691 - { 692 - struct dvb_usb_device *d = adap->dev; 693 - struct rc_dev *rc; 694 - int ret; 695 - 696 - info("STA Configuring Remote"); 697 - 698 - rc = rc_allocate_device(); 699 - if (!rc) 700 - return -ENOMEM; 701 - 702 - usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); 703 - strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); 704 - 705 - rc->input_name = "LME2510 Remote Control"; 706 - rc->input_phys = d->rc_phys; 707 - rc->map_name = RC_MAP_LME2510; 708 - rc->driver_name = "LME 2510"; 709 - usb_to_input_id(d->udev, &rc->input_id); 710 - 711 - ret = rc_register_device(rc); 712 - if (ret) { 713 - rc_free_device(rc); 714 - return ret; 715 - } 716 - d->rc_dev = rc; 717 - 718 - /* Start the Interrupt */ 719 - ret = lme2510_int_read(adap); 720 - if (ret < 0) { 721 - rc_unregister_device(rc); 722 - info("INT Unable to start Interrupt Service"); 723 - return -ENODEV; 724 - } 725 - 726 - return 0; 727 - } 728 - 729 694 static u8 check_sum(u8 *p, u8 len) 730 695 { 731 696 u8 sum = 0; ··· 788 831 789 832 cold_fw = !cold; 790 833 791 - if (udev->descriptor.idProduct == 0x1122) { 834 + if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) { 792 835 switch (dvb_usb_lme2510_firmware) { 793 836 default: 794 837 dvb_usb_lme2510_firmware = TUNER_S0194; ··· 1010 1053 1011 1054 1012 1055 end: if (ret) { 1013 - kfree(adap->fe); 1014 - adap->fe = NULL; 1056 + if (adap->fe) { 1057 + dvb_frontend_detach(adap->fe); 1058 + adap->fe = NULL; 1059 + } 1060 + adap->dev->props.rc.core.rc_codes = NULL; 1015 1061 return -ENODEV; 1016 1062 } 1017 1063 ··· 1057 1097 return -ENODEV; 1058 1098 } 1059 1099 1060 - /* Start the Interrupt & Remote*/ 1061 - ret = lme2510_int_service(adap); 1100 + /* Start the Interrupt*/ 1101 + ret = lme2510_int_read(adap); 1102 + if (ret < 0) { 1103 + info("INT Unable to start Interrupt Service"); 1104 + return -ENODEV; 1105 + } 1062 1106 1063 1107 return ret; 1064 1108 } ··· 1168 1204 } 1169 1205 } 1170 1206 }, 1207 + .rc.core = { 1208 + .protocol = RC_TYPE_NEC, 1209 + .module_name = "LME2510 Remote Control", 1210 + .allowed_protos = RC_TYPE_NEC, 1211 + .rc_codes = RC_MAP_LME2510, 1212 + }, 1171 1213 .power_ctrl = lme2510_powerup, 1172 1214 .identify_state = lme2510_identify_state, 1173 1215 .i2c_algo = &lme2510_i2c_algo, ··· 1216 1246 } 1217 1247 } 1218 1248 }, 1249 + .rc.core = { 1250 + .protocol = RC_TYPE_NEC, 1251 + .module_name = "LME2510 Remote Control", 1252 + .allowed_protos = RC_TYPE_NEC, 1253 + .rc_codes = RC_MAP_LME2510, 1254 + }, 1219 1255 .power_ctrl = lme2510_powerup, 1220 1256 .identify_state = lme2510_identify_state, 1221 1257 .i2c_algo = &lme2510_i2c_algo, ··· 1245 1269 adap->feedcount = 0; 1246 1270 } 1247 1271 1248 - if (st->lme_urb != NULL) { 1272 + if (st->usb_buffer != NULL) { 1249 1273 st->i2c_talk_onoff = 1; 1250 1274 st->signal_lock = 0; 1251 1275 st->signal_level = 0; 1252 1276 st->signal_sn = 0; 1253 1277 buffer = st->usb_buffer; 1278 + } 1279 + 1280 + if (st->lme_urb != NULL) { 1254 1281 usb_kill_urb(st->lme_urb); 1255 1282 usb_free_coherent(d->udev, 5000, st->buffer, 1256 1283 st->lme_urb->transfer_dma); 1257 1284 info("Interrupt Service Stopped"); 1258 - rc_unregister_device(d->rc_dev); 1259 - info("Remote Stopped"); 1260 1285 } 1286 + 1261 1287 return buffer; 1262 1288 } 1263 1289 ··· 1271 1293 if (d != NULL) { 1272 1294 usb_buffer = lme2510_exit_int(d); 1273 1295 dvb_usb_device_exit(intf); 1274 - kfree(usb_buffer); 1296 + if (usb_buffer != NULL) 1297 + kfree(usb_buffer); 1275 1298 } 1276 1299 } 1277 1300 ··· 1306 1327 1307 1328 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); 1308 1329 MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); 1309 - MODULE_VERSION("1.86"); 1330 + MODULE_VERSION("1.88"); 1310 1331 MODULE_LICENSE("GPL");
+1 -1
drivers/media/dvb/frontends/stb0899_algo.c
··· 23 23 #include "stb0899_priv.h" 24 24 #include "stb0899_reg.h" 25 25 26 - inline u32 stb0899_do_div(u64 n, u32 d) 26 + static inline u32 stb0899_do_div(u64 n, u32 d) 27 27 { 28 28 /* wrap do_div() for ease of use */ 29 29
-1
drivers/media/dvb/frontends/tda8261.c
··· 224 224 } 225 225 226 226 EXPORT_SYMBOL(tda8261_attach); 227 - MODULE_PARM_DESC(verbose, "Set verbosity level"); 228 227 229 228 MODULE_AUTHOR("Manu Abraham"); 230 229 MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
+1 -1
drivers/media/radio/radio-wl1273.c
··· 1382 1382 1383 1383 switch (ctrl->id) { 1384 1384 case V4L2_CID_TUNE_ANTENNA_CAPACITOR: 1385 - ctrl->val = wl1273_fm_get_tx_ctune(radio); 1385 + ctrl->cur.val = wl1273_fm_get_tx_ctune(radio); 1386 1386 break; 1387 1387 1388 1388 default:
+1 -1
drivers/media/radio/wl128x/fmdrv_v4l2.c
··· 191 191 192 192 switch (ctrl->id) { 193 193 case V4L2_CID_TUNE_ANTENNA_CAPACITOR: 194 - ctrl->val = fm_tx_get_tune_cap_val(fmdev); 194 + ctrl->cur.val = fm_tx_get_tune_cap_val(fmdev); 195 195 break; 196 196 default: 197 197 fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id);
+12
drivers/media/rc/Kconfig
··· 148 148 To compile this driver as a module, choose M here: the 149 149 module will be called ite-cir. 150 150 151 + config IR_FINTEK 152 + tristate "Fintek Consumer Infrared Transceiver" 153 + depends on PNP 154 + depends on RC_CORE 155 + ---help--- 156 + Say Y here to enable support for integrated infrared receiver 157 + /transciever made by Fintek. This chip is found on assorted 158 + Jetway motherboards (and of course, possibly others). 159 + 160 + To compile this driver as a module, choose M here: the 161 + module will be called fintek-cir. 162 + 151 163 config IR_NUVOTON 152 164 tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" 153 165 depends on PNP
+1
drivers/media/rc/Makefile
··· 16 16 obj-$(CONFIG_IR_IMON) += imon.o 17 17 obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o 18 18 obj-$(CONFIG_IR_MCEUSB) += mceusb.o 19 + obj-$(CONFIG_IR_FINTEK) += fintek-cir.o 19 20 obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o 20 21 obj-$(CONFIG_IR_ENE) += ene_ir.o 21 22 obj-$(CONFIG_IR_REDRAT3) += redrat3.o
+684
drivers/media/rc/fintek-cir.c
··· 1 + /* 2 + * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR 3 + * 4 + * Copyright (C) 2011 Jarod Wilson <jarod@redhat.com> 5 + * 6 + * Special thanks to Fintek for providing hardware and spec sheets. 7 + * This driver is based upon the nuvoton, ite and ene drivers for 8 + * similar hardware. 9 + * 10 + * This program is free software; you can redistribute it and/or 11 + * modify it under the terms of the GNU General Public License as 12 + * published by the Free Software Foundation; either version 2 of the 13 + * License, or (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, but 16 + * WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 + * General Public License for more details. 19 + * 20 + * You should have received a copy of the GNU General Public License 21 + * along with this program; if not, write to the Free Software 22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 + * USA 24 + */ 25 + 26 + #include <linux/kernel.h> 27 + #include <linux/module.h> 28 + #include <linux/pnp.h> 29 + #include <linux/io.h> 30 + #include <linux/interrupt.h> 31 + #include <linux/sched.h> 32 + #include <linux/slab.h> 33 + #include <media/rc-core.h> 34 + #include <linux/pci_ids.h> 35 + 36 + #include "fintek-cir.h" 37 + 38 + /* write val to config reg */ 39 + static inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg) 40 + { 41 + fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)", 42 + __func__, reg, val, fintek->cr_ip, fintek->cr_dp); 43 + outb(reg, fintek->cr_ip); 44 + outb(val, fintek->cr_dp); 45 + } 46 + 47 + /* read val from config reg */ 48 + static inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg) 49 + { 50 + u8 val; 51 + 52 + outb(reg, fintek->cr_ip); 53 + val = inb(fintek->cr_dp); 54 + 55 + fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)", 56 + __func__, reg, val, fintek->cr_ip, fintek->cr_dp); 57 + return val; 58 + } 59 + 60 + /* update config register bit without changing other bits */ 61 + static inline void fintek_set_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg) 62 + { 63 + u8 tmp = fintek_cr_read(fintek, reg) | val; 64 + fintek_cr_write(fintek, tmp, reg); 65 + } 66 + 67 + /* clear config register bit without changing other bits */ 68 + static inline void fintek_clear_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg) 69 + { 70 + u8 tmp = fintek_cr_read(fintek, reg) & ~val; 71 + fintek_cr_write(fintek, tmp, reg); 72 + } 73 + 74 + /* enter config mode */ 75 + static inline void fintek_config_mode_enable(struct fintek_dev *fintek) 76 + { 77 + /* Enabling Config Mode explicitly requires writing 2x */ 78 + outb(CONFIG_REG_ENABLE, fintek->cr_ip); 79 + outb(CONFIG_REG_ENABLE, fintek->cr_ip); 80 + } 81 + 82 + /* exit config mode */ 83 + static inline void fintek_config_mode_disable(struct fintek_dev *fintek) 84 + { 85 + outb(CONFIG_REG_DISABLE, fintek->cr_ip); 86 + } 87 + 88 + /* 89 + * When you want to address a specific logical device, write its logical 90 + * device number to GCR_LOGICAL_DEV_NO 91 + */ 92 + static inline void fintek_select_logical_dev(struct fintek_dev *fintek, u8 ldev) 93 + { 94 + fintek_cr_write(fintek, ldev, GCR_LOGICAL_DEV_NO); 95 + } 96 + 97 + /* write val to cir config register */ 98 + static inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 offset) 99 + { 100 + outb(val, fintek->cir_addr + offset); 101 + } 102 + 103 + /* read val from cir config register */ 104 + static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset) 105 + { 106 + u8 val; 107 + 108 + val = inb(fintek->cir_addr + offset); 109 + 110 + return val; 111 + } 112 + 113 + #define pr_reg(text, ...) \ 114 + printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__) 115 + 116 + /* dump current cir register contents */ 117 + static void cir_dump_regs(struct fintek_dev *fintek) 118 + { 119 + fintek_config_mode_enable(fintek); 120 + fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 121 + 122 + pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); 123 + pr_reg(" * CR CIR BASE ADDR: 0x%x\n", 124 + (fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) | 125 + fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO)); 126 + pr_reg(" * CR CIR IRQ NUM: 0x%x\n", 127 + fintek_cr_read(fintek, CIR_CR_IRQ_SEL)); 128 + 129 + fintek_config_mode_disable(fintek); 130 + 131 + pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME); 132 + pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS)); 133 + pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL)); 134 + pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA)); 135 + pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL)); 136 + pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA)); 137 + } 138 + 139 + /* detect hardware features */ 140 + static int fintek_hw_detect(struct fintek_dev *fintek) 141 + { 142 + unsigned long flags; 143 + u8 chip_major, chip_minor; 144 + u8 vendor_major, vendor_minor; 145 + u8 portsel, ir_class; 146 + u16 vendor; 147 + int ret = 0; 148 + 149 + fintek_config_mode_enable(fintek); 150 + 151 + /* Check if we're using config port 0x4e or 0x2e */ 152 + portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL); 153 + if (portsel == 0xff) { 154 + fit_pr(KERN_INFO, "first portsel read was bunk, trying alt"); 155 + fintek_config_mode_disable(fintek); 156 + fintek->cr_ip = CR_INDEX_PORT2; 157 + fintek->cr_dp = CR_DATA_PORT2; 158 + fintek_config_mode_enable(fintek); 159 + portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL); 160 + } 161 + fit_dbg("portsel reg: 0x%02x", portsel); 162 + 163 + ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS); 164 + fit_dbg("ir_class reg: 0x%02x", ir_class); 165 + 166 + switch (ir_class) { 167 + case CLASS_RX_2TX: 168 + case CLASS_RX_1TX: 169 + fintek->hw_tx_capable = true; 170 + break; 171 + case CLASS_RX_ONLY: 172 + default: 173 + fintek->hw_tx_capable = false; 174 + break; 175 + } 176 + 177 + chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI); 178 + chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO); 179 + 180 + vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI); 181 + vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO); 182 + vendor = vendor_major << 8 | vendor_minor; 183 + 184 + if (vendor != VENDOR_ID_FINTEK) 185 + fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor); 186 + else 187 + fit_dbg("Read Fintek vendor ID from chip"); 188 + 189 + fintek_config_mode_disable(fintek); 190 + 191 + spin_lock_irqsave(&fintek->fintek_lock, flags); 192 + fintek->chip_major = chip_major; 193 + fintek->chip_minor = chip_minor; 194 + fintek->chip_vendor = vendor; 195 + spin_unlock_irqrestore(&fintek->fintek_lock, flags); 196 + 197 + return ret; 198 + } 199 + 200 + static void fintek_cir_ldev_init(struct fintek_dev *fintek) 201 + { 202 + /* Select CIR logical device and enable */ 203 + fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 204 + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); 205 + 206 + /* Write allocated CIR address and IRQ information to hardware */ 207 + fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI); 208 + fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO); 209 + 210 + fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL); 211 + 212 + fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)", 213 + fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len); 214 + } 215 + 216 + /* enable CIR interrupts */ 217 + static void fintek_enable_cir_irq(struct fintek_dev *fintek) 218 + { 219 + fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS); 220 + } 221 + 222 + static void fintek_cir_regs_init(struct fintek_dev *fintek) 223 + { 224 + /* clear any and all stray interrupts */ 225 + fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 226 + 227 + /* and finally, enable interrupts */ 228 + fintek_enable_cir_irq(fintek); 229 + } 230 + 231 + static void fintek_enable_wake(struct fintek_dev *fintek) 232 + { 233 + fintek_config_mode_enable(fintek); 234 + fintek_select_logical_dev(fintek, LOGICAL_DEV_ACPI); 235 + 236 + /* Allow CIR PME's to wake system */ 237 + fintek_set_reg_bit(fintek, ACPI_WAKE_EN_CIR_BIT, LDEV_ACPI_WAKE_EN_REG); 238 + /* Enable CIR PME's */ 239 + fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_EN_REG); 240 + /* Clear CIR PME status register */ 241 + fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_CLR_REG); 242 + /* Save state */ 243 + fintek_set_reg_bit(fintek, ACPI_STATE_CIR_BIT, LDEV_ACPI_STATE_REG); 244 + 245 + fintek_config_mode_disable(fintek); 246 + } 247 + 248 + static int fintek_cmdsize(u8 cmd, u8 subcmd) 249 + { 250 + int datasize = 0; 251 + 252 + switch (cmd) { 253 + case BUF_COMMAND_NULL: 254 + if (subcmd == BUF_HW_CMD_HEADER) 255 + datasize = 1; 256 + break; 257 + case BUF_HW_CMD_HEADER: 258 + if (subcmd == BUF_CMD_G_REVISION) 259 + datasize = 2; 260 + break; 261 + case BUF_COMMAND_HEADER: 262 + switch (subcmd) { 263 + case BUF_CMD_S_CARRIER: 264 + case BUF_CMD_S_TIMEOUT: 265 + case BUF_RSP_PULSE_COUNT: 266 + datasize = 2; 267 + break; 268 + case BUF_CMD_SIG_END: 269 + case BUF_CMD_S_TXMASK: 270 + case BUF_CMD_S_RXSENSOR: 271 + datasize = 1; 272 + break; 273 + } 274 + } 275 + 276 + return datasize; 277 + } 278 + 279 + /* process ir data stored in driver buffer */ 280 + static void fintek_process_rx_ir_data(struct fintek_dev *fintek) 281 + { 282 + DEFINE_IR_RAW_EVENT(rawir); 283 + u8 sample; 284 + int i; 285 + 286 + for (i = 0; i < fintek->pkts; i++) { 287 + sample = fintek->buf[i]; 288 + switch (fintek->parser_state) { 289 + case CMD_HEADER: 290 + fintek->cmd = sample; 291 + if ((fintek->cmd == BUF_COMMAND_HEADER) || 292 + ((fintek->cmd & BUF_COMMAND_MASK) != 293 + BUF_PULSE_BIT)) { 294 + fintek->parser_state = SUBCMD; 295 + continue; 296 + } 297 + fintek->rem = (fintek->cmd & BUF_LEN_MASK); 298 + fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem); 299 + if (fintek->rem) 300 + fintek->parser_state = PARSE_IRDATA; 301 + else 302 + ir_raw_event_reset(fintek->rdev); 303 + break; 304 + case SUBCMD: 305 + fintek->rem = fintek_cmdsize(fintek->cmd, sample); 306 + fintek->parser_state = CMD_DATA; 307 + break; 308 + case CMD_DATA: 309 + fintek->rem--; 310 + break; 311 + case PARSE_IRDATA: 312 + fintek->rem--; 313 + init_ir_raw_event(&rawir); 314 + rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); 315 + rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK) 316 + * CIR_SAMPLE_PERIOD); 317 + 318 + fit_dbg("Storing %s with duration %d", 319 + rawir.pulse ? "pulse" : "space", 320 + rawir.duration); 321 + ir_raw_event_store_with_filter(fintek->rdev, &rawir); 322 + break; 323 + } 324 + 325 + if ((fintek->parser_state != CMD_HEADER) && !fintek->rem) 326 + fintek->parser_state = CMD_HEADER; 327 + } 328 + 329 + fintek->pkts = 0; 330 + 331 + fit_dbg("Calling ir_raw_event_handle"); 332 + ir_raw_event_handle(fintek->rdev); 333 + } 334 + 335 + /* copy data from hardware rx register into driver buffer */ 336 + static void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs) 337 + { 338 + unsigned long flags; 339 + u8 sample, status; 340 + 341 + spin_lock_irqsave(&fintek->fintek_lock, flags); 342 + 343 + /* 344 + * We must read data from CIR_RX_DATA until the hardware IR buffer 345 + * is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in 346 + * the CIR_STATUS register 347 + */ 348 + do { 349 + sample = fintek_cir_reg_read(fintek, CIR_RX_DATA); 350 + fit_dbg("%s: sample: 0x%02x", __func__, sample); 351 + 352 + fintek->buf[fintek->pkts] = sample; 353 + fintek->pkts++; 354 + 355 + status = fintek_cir_reg_read(fintek, CIR_STATUS); 356 + if (!(status & CIR_STATUS_IRQ_EN)) 357 + break; 358 + } while (status & rx_irqs); 359 + 360 + fintek_process_rx_ir_data(fintek); 361 + 362 + spin_unlock_irqrestore(&fintek->fintek_lock, flags); 363 + } 364 + 365 + static void fintek_cir_log_irqs(u8 status) 366 + { 367 + fit_pr(KERN_INFO, "IRQ 0x%02x:%s%s%s%s%s", status, 368 + status & CIR_STATUS_IRQ_EN ? " IRQEN" : "", 369 + status & CIR_STATUS_TX_FINISH ? " TXF" : "", 370 + status & CIR_STATUS_TX_UNDERRUN ? " TXU" : "", 371 + status & CIR_STATUS_RX_TIMEOUT ? " RXTO" : "", 372 + status & CIR_STATUS_RX_RECEIVE ? " RXOK" : ""); 373 + } 374 + 375 + /* interrupt service routine for incoming and outgoing CIR data */ 376 + static irqreturn_t fintek_cir_isr(int irq, void *data) 377 + { 378 + struct fintek_dev *fintek = data; 379 + u8 status, rx_irqs; 380 + 381 + fit_dbg_verbose("%s firing", __func__); 382 + 383 + fintek_config_mode_enable(fintek); 384 + fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 385 + fintek_config_mode_disable(fintek); 386 + 387 + /* 388 + * Get IR Status register contents. Write 1 to ack/clear 389 + * 390 + * bit: reg name - description 391 + * 3: TX_FINISH - TX is finished 392 + * 2: TX_UNDERRUN - TX underrun 393 + * 1: RX_TIMEOUT - RX data timeout 394 + * 0: RX_RECEIVE - RX data received 395 + */ 396 + status = fintek_cir_reg_read(fintek, CIR_STATUS); 397 + if (!(status & CIR_STATUS_IRQ_MASK) || status == 0xff) { 398 + fit_dbg_verbose("%s exiting, IRSTS 0x%02x", __func__, status); 399 + fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 400 + return IRQ_RETVAL(IRQ_NONE); 401 + } 402 + 403 + if (debug) 404 + fintek_cir_log_irqs(status); 405 + 406 + rx_irqs = status & (CIR_STATUS_RX_RECEIVE | CIR_STATUS_RX_TIMEOUT); 407 + if (rx_irqs) 408 + fintek_get_rx_ir_data(fintek, rx_irqs); 409 + 410 + /* ack/clear all irq flags we've got */ 411 + fintek_cir_reg_write(fintek, status, CIR_STATUS); 412 + 413 + fit_dbg_verbose("%s done", __func__); 414 + return IRQ_RETVAL(IRQ_HANDLED); 415 + } 416 + 417 + static void fintek_enable_cir(struct fintek_dev *fintek) 418 + { 419 + /* set IRQ enabled */ 420 + fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS); 421 + 422 + fintek_config_mode_enable(fintek); 423 + 424 + /* enable the CIR logical device */ 425 + fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 426 + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); 427 + 428 + fintek_config_mode_disable(fintek); 429 + 430 + /* clear all pending interrupts */ 431 + fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 432 + 433 + /* enable interrupts */ 434 + fintek_enable_cir_irq(fintek); 435 + } 436 + 437 + static void fintek_disable_cir(struct fintek_dev *fintek) 438 + { 439 + fintek_config_mode_enable(fintek); 440 + 441 + /* disable the CIR logical device */ 442 + fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 443 + fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); 444 + 445 + fintek_config_mode_disable(fintek); 446 + } 447 + 448 + static int fintek_open(struct rc_dev *dev) 449 + { 450 + struct fintek_dev *fintek = dev->priv; 451 + unsigned long flags; 452 + 453 + spin_lock_irqsave(&fintek->fintek_lock, flags); 454 + fintek_enable_cir(fintek); 455 + spin_unlock_irqrestore(&fintek->fintek_lock, flags); 456 + 457 + return 0; 458 + } 459 + 460 + static void fintek_close(struct rc_dev *dev) 461 + { 462 + struct fintek_dev *fintek = dev->priv; 463 + unsigned long flags; 464 + 465 + spin_lock_irqsave(&fintek->fintek_lock, flags); 466 + fintek_disable_cir(fintek); 467 + spin_unlock_irqrestore(&fintek->fintek_lock, flags); 468 + } 469 + 470 + /* Allocate memory, probe hardware, and initialize everything */ 471 + static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) 472 + { 473 + struct fintek_dev *fintek; 474 + struct rc_dev *rdev; 475 + int ret = -ENOMEM; 476 + 477 + fintek = kzalloc(sizeof(struct fintek_dev), GFP_KERNEL); 478 + if (!fintek) 479 + return ret; 480 + 481 + /* input device for IR remote (and tx) */ 482 + rdev = rc_allocate_device(); 483 + if (!rdev) 484 + goto failure; 485 + 486 + ret = -ENODEV; 487 + /* validate pnp resources */ 488 + if (!pnp_port_valid(pdev, 0)) { 489 + dev_err(&pdev->dev, "IR PNP Port not valid!\n"); 490 + goto failure; 491 + } 492 + 493 + if (!pnp_irq_valid(pdev, 0)) { 494 + dev_err(&pdev->dev, "IR PNP IRQ not valid!\n"); 495 + goto failure; 496 + } 497 + 498 + fintek->cir_addr = pnp_port_start(pdev, 0); 499 + fintek->cir_irq = pnp_irq(pdev, 0); 500 + fintek->cir_port_len = pnp_port_len(pdev, 0); 501 + 502 + fintek->cr_ip = CR_INDEX_PORT; 503 + fintek->cr_dp = CR_DATA_PORT; 504 + 505 + spin_lock_init(&fintek->fintek_lock); 506 + 507 + ret = -EBUSY; 508 + /* now claim resources */ 509 + if (!request_region(fintek->cir_addr, 510 + fintek->cir_port_len, FINTEK_DRIVER_NAME)) 511 + goto failure; 512 + 513 + if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED, 514 + FINTEK_DRIVER_NAME, (void *)fintek)) 515 + goto failure; 516 + 517 + pnp_set_drvdata(pdev, fintek); 518 + fintek->pdev = pdev; 519 + 520 + ret = fintek_hw_detect(fintek); 521 + if (ret) 522 + goto failure; 523 + 524 + /* Initialize CIR & CIR Wake Logical Devices */ 525 + fintek_config_mode_enable(fintek); 526 + fintek_cir_ldev_init(fintek); 527 + fintek_config_mode_disable(fintek); 528 + 529 + /* Initialize CIR & CIR Wake Config Registers */ 530 + fintek_cir_regs_init(fintek); 531 + 532 + /* Set up the rc device */ 533 + rdev->priv = fintek; 534 + rdev->driver_type = RC_DRIVER_IR_RAW; 535 + rdev->allowed_protos = RC_TYPE_ALL; 536 + rdev->open = fintek_open; 537 + rdev->close = fintek_close; 538 + rdev->input_name = FINTEK_DESCRIPTION; 539 + rdev->input_phys = "fintek/cir0"; 540 + rdev->input_id.bustype = BUS_HOST; 541 + rdev->input_id.vendor = VENDOR_ID_FINTEK; 542 + rdev->input_id.product = fintek->chip_major; 543 + rdev->input_id.version = fintek->chip_minor; 544 + rdev->dev.parent = &pdev->dev; 545 + rdev->driver_name = FINTEK_DRIVER_NAME; 546 + rdev->map_name = RC_MAP_RC6_MCE; 547 + rdev->timeout = US_TO_NS(1000); 548 + /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ 549 + rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); 550 + 551 + ret = rc_register_device(rdev); 552 + if (ret) 553 + goto failure; 554 + 555 + device_init_wakeup(&pdev->dev, true); 556 + fintek->rdev = rdev; 557 + fit_pr(KERN_NOTICE, "driver has been successfully loaded\n"); 558 + if (debug) 559 + cir_dump_regs(fintek); 560 + 561 + return 0; 562 + 563 + failure: 564 + if (fintek->cir_irq) 565 + free_irq(fintek->cir_irq, fintek); 566 + if (fintek->cir_addr) 567 + release_region(fintek->cir_addr, fintek->cir_port_len); 568 + 569 + rc_free_device(rdev); 570 + kfree(fintek); 571 + 572 + return ret; 573 + } 574 + 575 + static void __devexit fintek_remove(struct pnp_dev *pdev) 576 + { 577 + struct fintek_dev *fintek = pnp_get_drvdata(pdev); 578 + unsigned long flags; 579 + 580 + spin_lock_irqsave(&fintek->fintek_lock, flags); 581 + /* disable CIR */ 582 + fintek_disable_cir(fintek); 583 + fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 584 + /* enable CIR Wake (for IR power-on) */ 585 + fintek_enable_wake(fintek); 586 + spin_unlock_irqrestore(&fintek->fintek_lock, flags); 587 + 588 + /* free resources */ 589 + free_irq(fintek->cir_irq, fintek); 590 + release_region(fintek->cir_addr, fintek->cir_port_len); 591 + 592 + rc_unregister_device(fintek->rdev); 593 + 594 + kfree(fintek); 595 + } 596 + 597 + static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state) 598 + { 599 + struct fintek_dev *fintek = pnp_get_drvdata(pdev); 600 + 601 + fit_dbg("%s called", __func__); 602 + 603 + /* disable all CIR interrupts */ 604 + fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 605 + 606 + fintek_config_mode_enable(fintek); 607 + 608 + /* disable cir logical dev */ 609 + fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 610 + fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); 611 + 612 + fintek_config_mode_disable(fintek); 613 + 614 + /* make sure wake is enabled */ 615 + fintek_enable_wake(fintek); 616 + 617 + return 0; 618 + } 619 + 620 + static int fintek_resume(struct pnp_dev *pdev) 621 + { 622 + int ret = 0; 623 + struct fintek_dev *fintek = pnp_get_drvdata(pdev); 624 + 625 + fit_dbg("%s called", __func__); 626 + 627 + /* open interrupt */ 628 + fintek_enable_cir_irq(fintek); 629 + 630 + /* Enable CIR logical device */ 631 + fintek_config_mode_enable(fintek); 632 + fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 633 + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); 634 + 635 + fintek_config_mode_disable(fintek); 636 + 637 + fintek_cir_regs_init(fintek); 638 + 639 + return ret; 640 + } 641 + 642 + static void fintek_shutdown(struct pnp_dev *pdev) 643 + { 644 + struct fintek_dev *fintek = pnp_get_drvdata(pdev); 645 + fintek_enable_wake(fintek); 646 + } 647 + 648 + static const struct pnp_device_id fintek_ids[] = { 649 + { "FIT0002", 0 }, /* CIR */ 650 + { "", 0 }, 651 + }; 652 + 653 + static struct pnp_driver fintek_driver = { 654 + .name = FINTEK_DRIVER_NAME, 655 + .id_table = fintek_ids, 656 + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, 657 + .probe = fintek_probe, 658 + .remove = __devexit_p(fintek_remove), 659 + .suspend = fintek_suspend, 660 + .resume = fintek_resume, 661 + .shutdown = fintek_shutdown, 662 + }; 663 + 664 + int fintek_init(void) 665 + { 666 + return pnp_register_driver(&fintek_driver); 667 + } 668 + 669 + void fintek_exit(void) 670 + { 671 + pnp_unregister_driver(&fintek_driver); 672 + } 673 + 674 + module_param(debug, int, S_IRUGO | S_IWUSR); 675 + MODULE_PARM_DESC(debug, "Enable debugging output"); 676 + 677 + MODULE_DEVICE_TABLE(pnp, fintek_ids); 678 + MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver"); 679 + 680 + MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); 681 + MODULE_LICENSE("GPL"); 682 + 683 + module_init(fintek_init); 684 + module_exit(fintek_exit);
+243
drivers/media/rc/fintek-cir.h
··· 1 + /* 2 + * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR 3 + * 4 + * Copyright (C) 2011 Jarod Wilson <jarod@redhat.com> 5 + * 6 + * Special thanks to Fintek for providing hardware and spec sheets. 7 + * This driver is based upon the nuvoton, ite and ene drivers for 8 + * similar hardware. 9 + * 10 + * This program is free software; you can redistribute it and/or 11 + * modify it under the terms of the GNU General Public License as 12 + * published by the Free Software Foundation; either version 2 of the 13 + * License, or (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, but 16 + * WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 + * General Public License for more details. 19 + * 20 + * You should have received a copy of the GNU General Public License 21 + * along with this program; if not, write to the Free Software 22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 + * USA 24 + */ 25 + 26 + #include <linux/spinlock.h> 27 + #include <linux/ioctl.h> 28 + 29 + /* platform driver name to register */ 30 + #define FINTEK_DRIVER_NAME "fintek-cir" 31 + #define FINTEK_DESCRIPTION "Fintek LPC SuperIO Consumer IR Transceiver" 32 + #define VENDOR_ID_FINTEK 0x1934 33 + 34 + 35 + /* debugging module parameter */ 36 + static int debug; 37 + 38 + #define fit_pr(level, text, ...) \ 39 + printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) 40 + 41 + #define fit_dbg(text, ...) \ 42 + if (debug) \ 43 + printk(KERN_DEBUG \ 44 + KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) 45 + 46 + #define fit_dbg_verbose(text, ...) \ 47 + if (debug > 1) \ 48 + printk(KERN_DEBUG \ 49 + KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) 50 + 51 + #define fit_dbg_wake(text, ...) \ 52 + if (debug > 2) \ 53 + printk(KERN_DEBUG \ 54 + KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) 55 + 56 + 57 + #define TX_BUF_LEN 256 58 + #define RX_BUF_LEN 32 59 + 60 + struct fintek_dev { 61 + struct pnp_dev *pdev; 62 + struct rc_dev *rdev; 63 + 64 + spinlock_t fintek_lock; 65 + 66 + /* for rx */ 67 + u8 buf[RX_BUF_LEN]; 68 + unsigned int pkts; 69 + 70 + struct { 71 + spinlock_t lock; 72 + u8 buf[TX_BUF_LEN]; 73 + unsigned int buf_count; 74 + unsigned int cur_buf_num; 75 + wait_queue_head_t queue; 76 + } tx; 77 + 78 + /* Config register index/data port pair */ 79 + u8 cr_ip; 80 + u8 cr_dp; 81 + 82 + /* hardware I/O settings */ 83 + unsigned long cir_addr; 84 + int cir_irq; 85 + int cir_port_len; 86 + 87 + /* hardware id */ 88 + u8 chip_major; 89 + u8 chip_minor; 90 + u16 chip_vendor; 91 + 92 + /* hardware features */ 93 + bool hw_learning_capable; 94 + bool hw_tx_capable; 95 + 96 + /* rx settings */ 97 + bool learning_enabled; 98 + bool carrier_detect_enabled; 99 + 100 + enum { 101 + CMD_HEADER = 0, 102 + SUBCMD, 103 + CMD_DATA, 104 + PARSE_IRDATA, 105 + } parser_state; 106 + 107 + u8 cmd, rem; 108 + 109 + /* carrier period = 1 / frequency */ 110 + u32 carrier; 111 + }; 112 + 113 + /* buffer packet constants, largely identical to mceusb.c */ 114 + #define BUF_PULSE_BIT 0x80 115 + #define BUF_LEN_MASK 0x1f 116 + #define BUF_SAMPLE_MASK 0x7f 117 + 118 + #define BUF_COMMAND_HEADER 0x9f 119 + #define BUF_COMMAND_MASK 0xe0 120 + #define BUF_COMMAND_NULL 0x00 121 + #define BUF_HW_CMD_HEADER 0xff 122 + #define BUF_CMD_G_REVISION 0x0b 123 + #define BUF_CMD_S_CARRIER 0x06 124 + #define BUF_CMD_S_TIMEOUT 0x0c 125 + #define BUF_CMD_SIG_END 0x01 126 + #define BUF_CMD_S_TXMASK 0x08 127 + #define BUF_CMD_S_RXSENSOR 0x14 128 + #define BUF_RSP_PULSE_COUNT 0x15 129 + 130 + #define CIR_SAMPLE_PERIOD 50 131 + 132 + /* 133 + * Configuration Register: 134 + * Index Port 135 + * Data Port 136 + */ 137 + #define CR_INDEX_PORT 0x2e 138 + #define CR_DATA_PORT 0x2f 139 + 140 + /* Possible alternate values, depends on how the chip is wired */ 141 + #define CR_INDEX_PORT2 0x4e 142 + #define CR_DATA_PORT2 0x4f 143 + 144 + /* 145 + * GCR_CONFIG_PORT_SEL bit 4 specifies which Index Port value is 146 + * active. 1 = 0x4e, 0 = 0x2e 147 + */ 148 + #define PORT_SEL_PORT_4E_EN 0x10 149 + 150 + /* Extended Function Mode enable/disable magic values */ 151 + #define CONFIG_REG_ENABLE 0x87 152 + #define CONFIG_REG_DISABLE 0xaa 153 + 154 + /* Chip IDs found in CR_CHIP_ID_{HI,LO} */ 155 + #define CHIP_ID_HIGH_F71809U 0x04 156 + #define CHIP_ID_LOW_F71809U 0x08 157 + 158 + /* 159 + * Global control regs we need to care about: 160 + * Global Control def. 161 + * Register name addr val. */ 162 + #define GCR_SOFTWARE_RESET 0x02 /* 0x00 */ 163 + #define GCR_LOGICAL_DEV_NO 0x07 /* 0x00 */ 164 + #define GCR_CHIP_ID_HI 0x20 /* 0x04 */ 165 + #define GCR_CHIP_ID_LO 0x21 /* 0x08 */ 166 + #define GCR_VENDOR_ID_HI 0x23 /* 0x19 */ 167 + #define GCR_VENDOR_ID_LO 0x24 /* 0x34 */ 168 + #define GCR_CONFIG_PORT_SEL 0x25 /* 0x01 */ 169 + #define GCR_KBMOUSE_WAKEUP 0x27 170 + 171 + #define LOGICAL_DEV_DISABLE 0x00 172 + #define LOGICAL_DEV_ENABLE 0x01 173 + 174 + /* Logical device number of the CIR function */ 175 + #define LOGICAL_DEV_CIR 0x05 176 + 177 + /* CIR Logical Device (LDN 0x08) config registers */ 178 + #define CIR_CR_COMMAND_INDEX 0x04 179 + #define CIR_CR_IRCS 0x05 /* Before host writes command to IR, host 180 + must set to 1. When host finshes write 181 + command to IR, host must clear to 0. */ 182 + #define CIR_CR_COMMAND_DATA 0x06 /* Host read or write comand data */ 183 + #define CIR_CR_CLASS 0x07 /* 0xff = rx-only, 0x66 = rx + 2 tx, 184 + 0x33 = rx + 1 tx */ 185 + #define CIR_CR_DEV_EN 0x30 /* bit0 = 1 enables CIR */ 186 + #define CIR_CR_BASE_ADDR_HI 0x60 /* MSB of CIR IO base addr */ 187 + #define CIR_CR_BASE_ADDR_LO 0x61 /* LSB of CIR IO base addr */ 188 + #define CIR_CR_IRQ_SEL 0x70 /* bits3-0 store CIR IRQ */ 189 + #define CIR_CR_PSOUT_STATUS 0xf1 190 + #define CIR_CR_WAKE_KEY3_ADDR 0xf8 191 + #define CIR_CR_WAKE_KEY3_CODE 0xf9 192 + #define CIR_CR_WAKE_KEY3_DC 0xfa 193 + #define CIR_CR_WAKE_CONTROL 0xfb 194 + #define CIR_CR_WAKE_KEY12_ADDR 0xfc 195 + #define CIR_CR_WAKE_KEY4_ADDR 0xfd 196 + #define CIR_CR_WAKE_KEY5_ADDR 0xfe 197 + 198 + #define CLASS_RX_ONLY 0xff 199 + #define CLASS_RX_2TX 0x66 200 + #define CLASS_RX_1TX 0x33 201 + 202 + /* CIR device registers */ 203 + #define CIR_STATUS 0x00 204 + #define CIR_RX_DATA 0x01 205 + #define CIR_TX_CONTROL 0x02 206 + #define CIR_TX_DATA 0x03 207 + #define CIR_CONTROL 0x04 208 + 209 + /* Bits to enable CIR wake */ 210 + #define LOGICAL_DEV_ACPI 0x01 211 + #define LDEV_ACPI_WAKE_EN_REG 0xe8 212 + #define ACPI_WAKE_EN_CIR_BIT 0x04 213 + 214 + #define LDEV_ACPI_PME_EN_REG 0xf0 215 + #define LDEV_ACPI_PME_CLR_REG 0xf1 216 + #define ACPI_PME_CIR_BIT 0x02 217 + 218 + #define LDEV_ACPI_STATE_REG 0xf4 219 + #define ACPI_STATE_CIR_BIT 0x20 220 + 221 + /* 222 + * CIR status register (0x00): 223 + * 7 - CIR_IRQ_EN (1 = enable CIR IRQ, 0 = disable) 224 + * 3 - TX_FINISH (1 when TX finished, write 1 to clear) 225 + * 2 - TX_UNDERRUN (1 on TX underrun, write 1 to clear) 226 + * 1 - RX_TIMEOUT (1 on RX timeout, write 1 to clear) 227 + * 0 - RX_RECEIVE (1 on RX receive, write 1 to clear) 228 + */ 229 + #define CIR_STATUS_IRQ_EN 0x80 230 + #define CIR_STATUS_TX_FINISH 0x08 231 + #define CIR_STATUS_TX_UNDERRUN 0x04 232 + #define CIR_STATUS_RX_TIMEOUT 0x02 233 + #define CIR_STATUS_RX_RECEIVE 0x01 234 + #define CIR_STATUS_IRQ_MASK 0x0f 235 + 236 + /* 237 + * CIR TX control register (0x02): 238 + * 7 - TX_START (1 to indicate TX start, auto-cleared when done) 239 + * 6 - TX_END (1 to indicate TX data written to TX fifo) 240 + */ 241 + #define CIR_TX_CONTROL_TX_START 0x80 242 + #define CIR_TX_CONTROL_TX_END 0x40 243 +
+67 -67
drivers/media/rc/keymaps/rc-lme2510.c
··· 14 14 15 15 static struct rc_map_table lme2510_rc[] = { 16 16 /* Type 1 - 26 buttons */ 17 - { 0xef12ba45, KEY_0 }, 18 - { 0xef12a05f, KEY_1 }, 19 - { 0xef12af50, KEY_2 }, 20 - { 0xef12a25d, KEY_3 }, 21 - { 0xef12be41, KEY_4 }, 22 - { 0xef12f50a, KEY_5 }, 23 - { 0xef12bd42, KEY_6 }, 24 - { 0xef12b847, KEY_7 }, 25 - { 0xef12b649, KEY_8 }, 26 - { 0xef12fa05, KEY_9 }, 27 - { 0xef12bc43, KEY_POWER }, 28 - { 0xef12b946, KEY_SUBTITLE }, 29 - { 0xef12f906, KEY_PAUSE }, 30 - { 0xef12fc03, KEY_MEDIA_REPEAT}, 31 - { 0xef12fd02, KEY_PAUSE }, 32 - { 0xef12a15e, KEY_VOLUMEUP }, 33 - { 0xef12a35c, KEY_VOLUMEDOWN }, 34 - { 0xef12f609, KEY_CHANNELUP }, 35 - { 0xef12e51a, KEY_CHANNELDOWN }, 36 - { 0xef12e11e, KEY_PLAY }, 37 - { 0xef12e41b, KEY_ZOOM }, 38 - { 0xef12a659, KEY_MUTE }, 39 - { 0xef12a55a, KEY_TV }, 40 - { 0xef12e718, KEY_RECORD }, 41 - { 0xef12f807, KEY_EPG }, 42 - { 0xef12fe01, KEY_STOP }, 17 + { 0x10ed45, KEY_0 }, 18 + { 0x10ed5f, KEY_1 }, 19 + { 0x10ed50, KEY_2 }, 20 + { 0x10ed5d, KEY_3 }, 21 + { 0x10ed41, KEY_4 }, 22 + { 0x10ed0a, KEY_5 }, 23 + { 0x10ed42, KEY_6 }, 24 + { 0x10ed47, KEY_7 }, 25 + { 0x10ed49, KEY_8 }, 26 + { 0x10ed05, KEY_9 }, 27 + { 0x10ed43, KEY_POWER }, 28 + { 0x10ed46, KEY_SUBTITLE }, 29 + { 0x10ed06, KEY_PAUSE }, 30 + { 0x10ed03, KEY_MEDIA_REPEAT}, 31 + { 0x10ed02, KEY_PAUSE }, 32 + { 0x10ed5e, KEY_VOLUMEUP }, 33 + { 0x10ed5c, KEY_VOLUMEDOWN }, 34 + { 0x10ed09, KEY_CHANNELUP }, 35 + { 0x10ed1a, KEY_CHANNELDOWN }, 36 + { 0x10ed1e, KEY_PLAY }, 37 + { 0x10ed1b, KEY_ZOOM }, 38 + { 0x10ed59, KEY_MUTE }, 39 + { 0x10ed5a, KEY_TV }, 40 + { 0x10ed18, KEY_RECORD }, 41 + { 0x10ed07, KEY_EPG }, 42 + { 0x10ed01, KEY_STOP }, 43 43 /* Type 2 - 20 buttons */ 44 - { 0xff40ea15, KEY_0 }, 45 - { 0xff40f708, KEY_1 }, 46 - { 0xff40f609, KEY_2 }, 47 - { 0xff40f50a, KEY_3 }, 48 - { 0xff40f30c, KEY_4 }, 49 - { 0xff40f20d, KEY_5 }, 50 - { 0xff40f10e, KEY_6 }, 51 - { 0xff40ef10, KEY_7 }, 52 - { 0xff40ee11, KEY_8 }, 53 - { 0xff40ed12, KEY_9 }, 54 - { 0xff40ff00, KEY_POWER }, 55 - { 0xff40fb04, KEY_MEDIA_REPEAT}, /* Recall */ 56 - { 0xff40e51a, KEY_PAUSE }, /* Timeshift */ 57 - { 0xff40fd02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ 58 - { 0xff40f906, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ 59 - { 0xff40fe01, KEY_CHANNELUP }, 60 - { 0xff40fa05, KEY_CHANNELDOWN }, 61 - { 0xff40eb14, KEY_ZOOM }, 62 - { 0xff40e718, KEY_RECORD }, 63 - { 0xff40e916, KEY_STOP }, 44 + { 0xbf15, KEY_0 }, 45 + { 0xbf08, KEY_1 }, 46 + { 0xbf09, KEY_2 }, 47 + { 0xbf0a, KEY_3 }, 48 + { 0xbf0c, KEY_4 }, 49 + { 0xbf0d, KEY_5 }, 50 + { 0xbf0e, KEY_6 }, 51 + { 0xbf10, KEY_7 }, 52 + { 0xbf11, KEY_8 }, 53 + { 0xbf12, KEY_9 }, 54 + { 0xbf00, KEY_POWER }, 55 + { 0xbf04, KEY_MEDIA_REPEAT}, /* Recall */ 56 + { 0xbf1a, KEY_PAUSE }, /* Timeshift */ 57 + { 0xbf02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ 58 + { 0xbf06, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ 59 + { 0xbf01, KEY_CHANNELUP }, 60 + { 0xbf05, KEY_CHANNELDOWN }, 61 + { 0xbf14, KEY_ZOOM }, 62 + { 0xbf18, KEY_RECORD }, 63 + { 0xbf16, KEY_STOP }, 64 64 /* Type 3 - 20 buttons */ 65 - { 0xff00e31c, KEY_0 }, 66 - { 0xff00f807, KEY_1 }, 67 - { 0xff00ea15, KEY_2 }, 68 - { 0xff00f609, KEY_3 }, 69 - { 0xff00e916, KEY_4 }, 70 - { 0xff00e619, KEY_5 }, 71 - { 0xff00f20d, KEY_6 }, 72 - { 0xff00f30c, KEY_7 }, 73 - { 0xff00e718, KEY_8 }, 74 - { 0xff00a15e, KEY_9 }, 75 - { 0xff00ba45, KEY_POWER }, 76 - { 0xff00bb44, KEY_MEDIA_REPEAT}, /* Recall */ 77 - { 0xff00b54a, KEY_PAUSE }, /* Timeshift */ 78 - { 0xff00b847, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ 79 - { 0xff00bc43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ 80 - { 0xff00b946, KEY_CHANNELUP }, 81 - { 0xff00bf40, KEY_CHANNELDOWN }, 82 - { 0xff00f708, KEY_ZOOM }, 83 - { 0xff00bd42, KEY_RECORD }, 84 - { 0xff00a55a, KEY_STOP }, 65 + { 0x1c, KEY_0 }, 66 + { 0x07, KEY_1 }, 67 + { 0x15, KEY_2 }, 68 + { 0x09, KEY_3 }, 69 + { 0x16, KEY_4 }, 70 + { 0x19, KEY_5 }, 71 + { 0x0d, KEY_6 }, 72 + { 0x0c, KEY_7 }, 73 + { 0x18, KEY_8 }, 74 + { 0x5e, KEY_9 }, 75 + { 0x45, KEY_POWER }, 76 + { 0x44, KEY_MEDIA_REPEAT}, /* Recall */ 77 + { 0x4a, KEY_PAUSE }, /* Timeshift */ 78 + { 0x47, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ 79 + { 0x43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ 80 + { 0x46, KEY_CHANNELUP }, 81 + { 0x40, KEY_CHANNELDOWN }, 82 + { 0x08, KEY_ZOOM }, 83 + { 0x42, KEY_RECORD }, 84 + { 0x5a, KEY_STOP }, 85 85 }; 86 86 87 87 static struct rc_map_list lme2510_map = { 88 88 .map = { 89 89 .scan = lme2510_rc, 90 90 .size = ARRAY_SIZE(lme2510_rc), 91 - .rc_type = RC_TYPE_UNKNOWN, 91 + .rc_type = RC_TYPE_NEC, 92 92 .name = RC_MAP_LME2510, 93 93 } 94 94 };
+4 -2
drivers/media/video/Kconfig
··· 687 687 688 688 config VIDEO_TIMBERDALE 689 689 tristate "Support for timberdale Video In/LogiWIN" 690 - depends on VIDEO_V4L2 && I2C 690 + depends on VIDEO_V4L2 && I2C && DMADEVICES 691 691 select DMA_ENGINE 692 692 select TIMB_DMA 693 693 select VIDEO_ADV7180 ··· 756 756 depends on I2C && VIDEO_V4L2 757 757 ---help--- 758 758 This driver supports NOON010PC30 CIF camera from Siliconfile 759 + 760 + source "drivers/media/video/m5mols/Kconfig" 759 761 760 762 config VIDEO_OMAP3 761 763 tristate "OMAP 3 Camera support (EXPERIMENTAL)" ··· 954 952 955 953 config VIDEO_S5P_MIPI_CSIS 956 954 tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" 957 - depends on VIDEO_V4L2 && PM_RUNTIME && VIDEO_V4L2_SUBDEV_API 955 + depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API 958 956 ---help--- 959 957 This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. 960 958
+1
drivers/media/video/Makefile
··· 69 69 obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o 70 70 obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o 71 71 obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o 72 + obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ 72 73 73 74 obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o 74 75 obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
+2 -2
drivers/media/video/cpia2/cpia2_v4l.c
··· 438 438 strcat(vc->card, " (676/"); 439 439 break; 440 440 default: 441 - strcat(vc->card, " (???/"); 441 + strcat(vc->card, " (XXX/"); 442 442 break; 443 443 } 444 444 switch (cam->params.version.sensor_flags) { ··· 458 458 strcat(vc->card, "500)"); 459 459 break; 460 460 default: 461 - strcat(vc->card, "???)"); 461 + strcat(vc->card, "XXX)"); 462 462 break; 463 463 } 464 464
+1 -1
drivers/media/video/gspca/kinect.c
··· 34 34 MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); 35 35 MODULE_LICENSE("GPL"); 36 36 37 - #ifdef DEBUG 37 + #ifdef GSPCA_DEBUG 38 38 int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK | 39 39 D_USBI | D_USBO | D_V4L2; 40 40 #endif
+5
drivers/media/video/m5mols/Kconfig
··· 1 + config VIDEO_M5MOLS 2 + tristate "Fujitsu M-5MOLS 8MP sensor support" 3 + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 4 + ---help--- 5 + This driver supports Fujitsu M-5MOLS camera sensor with ISP
+3
drivers/media/video/m5mols/Makefile
··· 1 + m5mols-objs := m5mols_core.o m5mols_controls.o m5mols_capture.o 2 + 3 + obj-$(CONFIG_VIDEO_M5MOLS) += m5mols.o
+296
drivers/media/video/m5mols/m5mols.h
··· 1 + /* 2 + * Header for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #ifndef M5MOLS_H 17 + #define M5MOLS_H 18 + 19 + #include <media/v4l2-subdev.h> 20 + #include "m5mols_reg.h" 21 + 22 + extern int m5mols_debug; 23 + 24 + #define to_m5mols(__sd) container_of(__sd, struct m5mols_info, sd) 25 + 26 + #define to_sd(__ctrl) \ 27 + (&container_of(__ctrl->handler, struct m5mols_info, handle)->sd) 28 + 29 + enum m5mols_restype { 30 + M5MOLS_RESTYPE_MONITOR, 31 + M5MOLS_RESTYPE_CAPTURE, 32 + M5MOLS_RESTYPE_MAX, 33 + }; 34 + 35 + /** 36 + * struct m5mols_resolution - structure for the resolution 37 + * @type: resolution type according to the pixel code 38 + * @width: width of the resolution 39 + * @height: height of the resolution 40 + * @reg: resolution preset register value 41 + */ 42 + struct m5mols_resolution { 43 + u8 reg; 44 + enum m5mols_restype type; 45 + u16 width; 46 + u16 height; 47 + }; 48 + 49 + /** 50 + * struct m5mols_exif - structure for the EXIF information of M-5MOLS 51 + * @exposure_time: exposure time register value 52 + * @shutter_speed: speed of the shutter register value 53 + * @aperture: aperture register value 54 + * @exposure_bias: it calls also EV bias 55 + * @iso_speed: ISO register value 56 + * @flash: status register value of the flash 57 + * @sdr: status register value of the Subject Distance Range 58 + * @qval: not written exact meaning in document 59 + */ 60 + struct m5mols_exif { 61 + u32 exposure_time; 62 + u32 shutter_speed; 63 + u32 aperture; 64 + u32 brightness; 65 + u32 exposure_bias; 66 + u16 iso_speed; 67 + u16 flash; 68 + u16 sdr; 69 + u16 qval; 70 + }; 71 + 72 + /** 73 + * struct m5mols_capture - Structure for the capture capability 74 + * @exif: EXIF information 75 + * @main: size in bytes of the main image 76 + * @thumb: size in bytes of the thumb image, if it was accompanied 77 + * @total: total size in bytes of the produced image 78 + */ 79 + struct m5mols_capture { 80 + struct m5mols_exif exif; 81 + u32 main; 82 + u32 thumb; 83 + u32 total; 84 + }; 85 + 86 + /** 87 + * struct m5mols_scenemode - structure for the scenemode capability 88 + * @metering: metering light register value 89 + * @ev_bias: EV bias register value 90 + * @wb_mode: mode which means the WhiteBalance is Auto or Manual 91 + * @wb_preset: whitebalance preset register value in the Manual mode 92 + * @chroma_en: register value whether the Chroma capability is enabled or not 93 + * @chroma_lvl: chroma's level register value 94 + * @edge_en: register value Whether the Edge capability is enabled or not 95 + * @edge_lvl: edge's level register value 96 + * @af_range: Auto Focus's range 97 + * @fd_mode: Face Detection mode 98 + * @mcc: Multi-axis Color Conversion which means emotion color 99 + * @light: status of the Light 100 + * @flash: status of the Flash 101 + * @tone: Tone color which means Contrast 102 + * @iso: ISO register value 103 + * @capt_mode: Mode of the Image Stabilization while the camera capturing 104 + * @wdr: Wide Dynamic Range register value 105 + * 106 + * The each value according to each scenemode is recommended in the documents. 107 + */ 108 + struct m5mols_scenemode { 109 + u32 metering; 110 + u32 ev_bias; 111 + u32 wb_mode; 112 + u32 wb_preset; 113 + u32 chroma_en; 114 + u32 chroma_lvl; 115 + u32 edge_en; 116 + u32 edge_lvl; 117 + u32 af_range; 118 + u32 fd_mode; 119 + u32 mcc; 120 + u32 light; 121 + u32 flash; 122 + u32 tone; 123 + u32 iso; 124 + u32 capt_mode; 125 + u32 wdr; 126 + }; 127 + 128 + /** 129 + * struct m5mols_version - firmware version information 130 + * @customer: customer information 131 + * @project: version of project information according to customer 132 + * @fw: firmware revision 133 + * @hw: hardware revision 134 + * @param: version of the parameter 135 + * @awb: Auto WhiteBalance algorithm version 136 + * @str: information about manufacturer and packaging vendor 137 + * @af: Auto Focus version 138 + * 139 + * The register offset starts the customer version at 0x0, and it ends 140 + * the awb version at 0x09. The customer, project information occupies 1 bytes 141 + * each. And also the fw, hw, param, awb each requires 2 bytes. The str is 142 + * unique string associated with firmware's version. It includes information 143 + * about manufacturer and the vendor of the sensor's packaging. The least 144 + * significant 2 bytes of the string indicate packaging manufacturer. 145 + */ 146 + #define VERSION_STRING_SIZE 22 147 + struct m5mols_version { 148 + u8 customer; 149 + u8 project; 150 + u16 fw; 151 + u16 hw; 152 + u16 param; 153 + u16 awb; 154 + u8 str[VERSION_STRING_SIZE]; 155 + u8 af; 156 + }; 157 + #define VERSION_SIZE sizeof(struct m5mols_version) 158 + 159 + /** 160 + * struct m5mols_info - M-5MOLS driver data structure 161 + * @pdata: platform data 162 + * @sd: v4l-subdev instance 163 + * @pad: media pad 164 + * @ffmt: current fmt according to resolution type 165 + * @res_type: current resolution type 166 + * @code: current code 167 + * @irq_waitq: waitqueue for the capture 168 + * @work_irq: workqueue for the IRQ 169 + * @flags: state variable for the interrupt handler 170 + * @handle: control handler 171 + * @autoexposure: Auto Exposure control 172 + * @exposure: Exposure control 173 + * @autowb: Auto White Balance control 174 + * @colorfx: Color effect control 175 + * @saturation: Saturation control 176 + * @zoom: Zoom control 177 + * @ver: information of the version 178 + * @cap: the capture mode attributes 179 + * @power: current sensor's power status 180 + * @ctrl_sync: true means all controls of the sensor are initialized 181 + * @int_capture: true means the capture interrupt is issued once 182 + * @lock_ae: true means the Auto Exposure is locked 183 + * @lock_awb: true means the Aut WhiteBalance is locked 184 + * @resolution: register value for current resolution 185 + * @interrupt: register value for current interrupt status 186 + * @mode: register value for current operation mode 187 + * @mode_save: register value for current operation mode for saving 188 + * @set_power: optional power callback to the board code 189 + */ 190 + struct m5mols_info { 191 + const struct m5mols_platform_data *pdata; 192 + struct v4l2_subdev sd; 193 + struct media_pad pad; 194 + struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; 195 + int res_type; 196 + enum v4l2_mbus_pixelcode code; 197 + wait_queue_head_t irq_waitq; 198 + struct work_struct work_irq; 199 + unsigned long flags; 200 + 201 + struct v4l2_ctrl_handler handle; 202 + /* Autoexposure/exposure control cluster */ 203 + struct { 204 + struct v4l2_ctrl *autoexposure; 205 + struct v4l2_ctrl *exposure; 206 + }; 207 + struct v4l2_ctrl *autowb; 208 + struct v4l2_ctrl *colorfx; 209 + struct v4l2_ctrl *saturation; 210 + struct v4l2_ctrl *zoom; 211 + 212 + struct m5mols_version ver; 213 + struct m5mols_capture cap; 214 + bool power; 215 + bool ctrl_sync; 216 + bool lock_ae; 217 + bool lock_awb; 218 + u8 resolution; 219 + u32 interrupt; 220 + u32 mode; 221 + u32 mode_save; 222 + int (*set_power)(struct device *dev, int on); 223 + }; 224 + 225 + #define ST_CAPT_IRQ 0 226 + 227 + #define is_powered(__info) (__info->power) 228 + #define is_ctrl_synced(__info) (__info->ctrl_sync) 229 + #define is_available_af(__info) (__info->ver.af) 230 + #define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code) 231 + #define is_manufacturer(__info, __manufacturer) \ 232 + (__info->ver.str[0] == __manufacturer[0] && \ 233 + __info->ver.str[1] == __manufacturer[1]) 234 + /* 235 + * I2C operation of the M-5MOLS 236 + * 237 + * The I2C read operation of the M-5MOLS requires 2 messages. The first 238 + * message sends the information about the command, command category, and total 239 + * message size. The second message is used to retrieve the data specifed in 240 + * the first message 241 + * 242 + * 1st message 2nd message 243 + * +-------+---+----------+-----+-------+ +------+------+------+------+ 244 + * | size1 | R | category | cmd | size2 | | d[0] | d[1] | d[2] | d[3] | 245 + * +-------+---+----------+-----+-------+ +------+------+------+------+ 246 + * - size1: message data size(5 in this case) 247 + * - size2: desired buffer size of the 2nd message 248 + * - d[0..3]: according to size2 249 + * 250 + * The I2C write operation needs just one message. The message includes 251 + * category, command, total size, and desired data. 252 + * 253 + * 1st message 254 + * +-------+---+----------+-----+------+------+------+------+ 255 + * | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] | 256 + * +-------+---+----------+-----+------+------+------+------+ 257 + * - d[0..3]: according to size1 258 + */ 259 + int m5mols_read(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); 260 + int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); 261 + int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value); 262 + 263 + /* 264 + * Mode operation of the M-5MOLS 265 + * 266 + * Changing the mode of the M-5MOLS is needed right executing order. 267 + * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed 268 + * by user. There are various categories associated with each mode. 269 + * 270 + * +============================================================+ 271 + * | mode | category | 272 + * +============================================================+ 273 + * | FLASH | FLASH(only after Stand-by or Power-on) | 274 + * | SYSTEM | SYSTEM(only after sensor arm-booting) | 275 + * | PARAMETER | PARAMETER | 276 + * | MONITOR | MONITOR(preview), Auto Focus, Face Detection | 277 + * | CAPTURE | Single CAPTURE, Preview(recording) | 278 + * +============================================================+ 279 + * 280 + * The available executing order between each modes are as follows: 281 + * PARAMETER <---> MONITOR <---> CAPTURE 282 + */ 283 + int m5mols_mode(struct m5mols_info *info, u32 mode); 284 + 285 + int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg); 286 + int m5mols_sync_controls(struct m5mols_info *info); 287 + int m5mols_start_capture(struct m5mols_info *info); 288 + int m5mols_do_scenemode(struct m5mols_info *info, u32 mode); 289 + int m5mols_lock_3a(struct m5mols_info *info, bool lock); 290 + int m5mols_set_ctrl(struct v4l2_ctrl *ctrl); 291 + 292 + /* The firmware function */ 293 + int m5mols_update_fw(struct v4l2_subdev *sd, 294 + int (*set_power)(struct m5mols_info *, bool)); 295 + 296 + #endif /* M5MOLS_H */
+191
drivers/media/video/m5mols/m5mols_capture.c
··· 1 + /* 2 + * The Capture code for Fujitsu M-5MOLS ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #include <linux/i2c.h> 17 + #include <linux/slab.h> 18 + #include <linux/irq.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/delay.h> 21 + #include <linux/version.h> 22 + #include <linux/gpio.h> 23 + #include <linux/regulator/consumer.h> 24 + #include <linux/videodev2.h> 25 + #include <linux/version.h> 26 + #include <media/v4l2-ctrls.h> 27 + #include <media/v4l2-device.h> 28 + #include <media/v4l2-subdev.h> 29 + #include <media/m5mols.h> 30 + 31 + #include "m5mols.h" 32 + #include "m5mols_reg.h" 33 + 34 + static int m5mols_capture_error_handler(struct m5mols_info *info, 35 + int timeout) 36 + { 37 + int ret; 38 + 39 + /* Disable all interrupts and clear relevant interrupt staus bits */ 40 + ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE, 41 + info->interrupt & ~(REG_INT_CAPTURE)); 42 + if (ret) 43 + return ret; 44 + 45 + if (timeout == 0) 46 + return -ETIMEDOUT; 47 + 48 + return 0; 49 + } 50 + /** 51 + * m5mols_read_rational - I2C read of a rational number 52 + * 53 + * Read numerator and denominator from registers @addr_num and @addr_den 54 + * respectively and return the division result in @val. 55 + */ 56 + static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num, 57 + u32 addr_den, u32 *val) 58 + { 59 + u32 num, den; 60 + 61 + int ret = m5mols_read(sd, addr_num, &num); 62 + if (!ret) 63 + ret = m5mols_read(sd, addr_den, &den); 64 + if (ret) 65 + return ret; 66 + *val = den == 0 ? 0 : num / den; 67 + return ret; 68 + } 69 + 70 + /** 71 + * m5mols_capture_info - Gather captured image information 72 + * 73 + * For now it gathers only EXIF information and file size. 74 + */ 75 + static int m5mols_capture_info(struct m5mols_info *info) 76 + { 77 + struct m5mols_exif *exif = &info->cap.exif; 78 + struct v4l2_subdev *sd = &info->sd; 79 + int ret; 80 + 81 + ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU, 82 + EXIF_INFO_EXPTIME_DE, &exif->exposure_time); 83 + if (ret) 84 + return ret; 85 + ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE, 86 + &exif->shutter_speed); 87 + if (ret) 88 + return ret; 89 + ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE, 90 + &exif->aperture); 91 + if (ret) 92 + return ret; 93 + ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE, 94 + &exif->brightness); 95 + if (ret) 96 + return ret; 97 + ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE, 98 + &exif->exposure_bias); 99 + if (ret) 100 + return ret; 101 + 102 + ret = m5mols_read(sd, EXIF_INFO_ISO, (u32 *)&exif->iso_speed); 103 + if (!ret) 104 + ret = m5mols_read(sd, EXIF_INFO_FLASH, (u32 *)&exif->flash); 105 + if (!ret) 106 + ret = m5mols_read(sd, EXIF_INFO_SDR, (u32 *)&exif->sdr); 107 + if (!ret) 108 + ret = m5mols_read(sd, EXIF_INFO_QVAL, (u32 *)&exif->qval); 109 + if (ret) 110 + return ret; 111 + 112 + if (!ret) 113 + ret = m5mols_read(sd, CAPC_IMAGE_SIZE, &info->cap.main); 114 + if (!ret) 115 + ret = m5mols_read(sd, CAPC_THUMB_SIZE, &info->cap.thumb); 116 + if (!ret) 117 + info->cap.total = info->cap.main + info->cap.thumb; 118 + 119 + return ret; 120 + } 121 + 122 + int m5mols_start_capture(struct m5mols_info *info) 123 + { 124 + struct v4l2_subdev *sd = &info->sd; 125 + u32 resolution = info->resolution; 126 + int timeout; 127 + int ret; 128 + 129 + /* 130 + * Preparing capture. Setting control & interrupt before entering 131 + * capture mode 132 + * 133 + * 1) change to MONITOR mode for operating control & interrupt 134 + * 2) set controls (considering v4l2_control value & lock 3A) 135 + * 3) set interrupt 136 + * 4) change to CAPTURE mode 137 + */ 138 + ret = m5mols_mode(info, REG_MONITOR); 139 + if (!ret) 140 + ret = m5mols_sync_controls(info); 141 + if (!ret) 142 + ret = m5mols_lock_3a(info, true); 143 + if (!ret) 144 + ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); 145 + if (!ret) 146 + ret = m5mols_mode(info, REG_CAPTURE); 147 + if (!ret) { 148 + /* Wait for capture interrupt, after changing capture mode */ 149 + timeout = wait_event_interruptible_timeout(info->irq_waitq, 150 + test_bit(ST_CAPT_IRQ, &info->flags), 151 + msecs_to_jiffies(2000)); 152 + if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) 153 + ret = m5mols_capture_error_handler(info, timeout); 154 + } 155 + if (!ret) 156 + ret = m5mols_lock_3a(info, false); 157 + if (ret) 158 + return ret; 159 + /* 160 + * Starting capture. Setting capture frame count and resolution and 161 + * the format(available format: JPEG, Bayer RAW, YUV). 162 + * 163 + * 1) select single or multi(enable to 25), format, size 164 + * 2) set interrupt 165 + * 3) start capture(for main image, now) 166 + * 4) get information 167 + * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device) 168 + */ 169 + ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); 170 + if (!ret) 171 + ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); 172 + if (!ret) 173 + ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); 174 + if (!ret) 175 + ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); 176 + if (!ret) 177 + ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); 178 + if (!ret) { 179 + /* Wait for the capture completion interrupt */ 180 + timeout = wait_event_interruptible_timeout(info->irq_waitq, 181 + test_bit(ST_CAPT_IRQ, &info->flags), 182 + msecs_to_jiffies(2000)); 183 + if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) { 184 + ret = m5mols_capture_info(info); 185 + if (!ret) 186 + v4l2_subdev_notify(sd, 0, &info->cap.total); 187 + } 188 + } 189 + 190 + return m5mols_capture_error_handler(info, timeout); 191 + }
+299
drivers/media/video/m5mols/m5mols_controls.c
··· 1 + /* 2 + * Controls for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #include <linux/i2c.h> 17 + #include <linux/delay.h> 18 + #include <linux/videodev2.h> 19 + #include <media/v4l2-ctrls.h> 20 + 21 + #include "m5mols.h" 22 + #include "m5mols_reg.h" 23 + 24 + static struct m5mols_scenemode m5mols_default_scenemode[] = { 25 + [REG_SCENE_NORMAL] = { 26 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 27 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 28 + REG_AF_NORMAL, REG_FD_OFF, 29 + REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF, 30 + 5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 31 + }, 32 + [REG_SCENE_PORTRAIT] = { 33 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 34 + REG_CHROMA_ON, 3, REG_EDGE_ON, 4, 35 + REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME, 36 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 37 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 38 + }, 39 + [REG_SCENE_LANDSCAPE] = { 40 + REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 41 + REG_CHROMA_ON, 4, REG_EDGE_ON, 6, 42 + REG_AF_NORMAL, REG_FD_OFF, 43 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 44 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 45 + }, 46 + [REG_SCENE_SPORTS] = { 47 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 48 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 49 + REG_AF_NORMAL, REG_FD_OFF, 50 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 51 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 52 + }, 53 + [REG_SCENE_PARTY_INDOOR] = { 54 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 55 + REG_CHROMA_ON, 4, REG_EDGE_ON, 5, 56 + REG_AF_NORMAL, REG_FD_OFF, 57 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 58 + 6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF, 59 + }, 60 + [REG_SCENE_BEACH_SNOW] = { 61 + REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0, 62 + REG_CHROMA_ON, 4, REG_EDGE_ON, 5, 63 + REG_AF_NORMAL, REG_FD_OFF, 64 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 65 + 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, 66 + }, 67 + [REG_SCENE_SUNSET] = { 68 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, 69 + REG_AWB_DAYLIGHT, 70 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 71 + REG_AF_NORMAL, REG_FD_OFF, 72 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 73 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 74 + }, 75 + [REG_SCENE_DAWN_DUSK] = { 76 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, 77 + REG_AWB_FLUORESCENT_1, 78 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 79 + REG_AF_NORMAL, REG_FD_OFF, 80 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 81 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 82 + }, 83 + [REG_SCENE_FALL] = { 84 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 85 + REG_CHROMA_ON, 5, REG_EDGE_ON, 5, 86 + REG_AF_NORMAL, REG_FD_OFF, 87 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 88 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 89 + }, 90 + [REG_SCENE_NIGHT] = { 91 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 92 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 93 + REG_AF_NORMAL, REG_FD_OFF, 94 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 95 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 96 + }, 97 + [REG_SCENE_AGAINST_LIGHT] = { 98 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 99 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 100 + REG_AF_NORMAL, REG_FD_OFF, 101 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 102 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 103 + }, 104 + [REG_SCENE_FIRE] = { 105 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 106 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 107 + REG_AF_NORMAL, REG_FD_OFF, 108 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 109 + 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, 110 + }, 111 + [REG_SCENE_TEXT] = { 112 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 113 + REG_CHROMA_ON, 3, REG_EDGE_ON, 7, 114 + REG_AF_MACRO, REG_FD_OFF, 115 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 116 + 6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON, 117 + }, 118 + [REG_SCENE_CANDLE] = { 119 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 120 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 121 + REG_AF_NORMAL, REG_FD_OFF, 122 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 123 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 124 + }, 125 + }; 126 + 127 + /** 128 + * m5mols_do_scenemode() - Change current scenemode 129 + * @mode: Desired mode of the scenemode 130 + * 131 + * WARNING: The execution order is important. Do not change the order. 132 + */ 133 + int m5mols_do_scenemode(struct m5mols_info *info, u32 mode) 134 + { 135 + struct v4l2_subdev *sd = &info->sd; 136 + struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode]; 137 + int ret; 138 + 139 + if (mode > REG_SCENE_CANDLE) 140 + return -EINVAL; 141 + 142 + ret = m5mols_lock_3a(info, false); 143 + if (!ret) 144 + ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode); 145 + if (!ret) 146 + ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode); 147 + if (!ret) 148 + ret = m5mols_write(sd, AE_MODE, scenemode.metering); 149 + if (!ret) 150 + ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias); 151 + if (!ret) 152 + ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode); 153 + if (!ret) 154 + ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset); 155 + if (!ret) 156 + ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en); 157 + if (!ret) 158 + ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl); 159 + if (!ret) 160 + ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en); 161 + if (!ret) 162 + ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl); 163 + if (!ret && is_available_af(info)) 164 + ret = m5mols_write(sd, AF_MODE, scenemode.af_range); 165 + if (!ret && is_available_af(info)) 166 + ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode); 167 + if (!ret) 168 + ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone); 169 + if (!ret) 170 + ret = m5mols_write(sd, AE_ISO, scenemode.iso); 171 + if (!ret) 172 + ret = m5mols_mode(info, REG_CAPTURE); 173 + if (!ret) 174 + ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr); 175 + if (!ret) 176 + ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc); 177 + if (!ret) 178 + ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light); 179 + if (!ret) 180 + ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash); 181 + if (!ret) 182 + ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode); 183 + if (!ret) 184 + ret = m5mols_mode(info, REG_MONITOR); 185 + 186 + return ret; 187 + } 188 + 189 + static int m5mols_lock_ae(struct m5mols_info *info, bool lock) 190 + { 191 + int ret = 0; 192 + 193 + if (info->lock_ae != lock) 194 + ret = m5mols_write(&info->sd, AE_LOCK, 195 + lock ? REG_AE_LOCK : REG_AE_UNLOCK); 196 + if (!ret) 197 + info->lock_ae = lock; 198 + 199 + return ret; 200 + } 201 + 202 + static int m5mols_lock_awb(struct m5mols_info *info, bool lock) 203 + { 204 + int ret = 0; 205 + 206 + if (info->lock_awb != lock) 207 + ret = m5mols_write(&info->sd, AWB_LOCK, 208 + lock ? REG_AWB_LOCK : REG_AWB_UNLOCK); 209 + if (!ret) 210 + info->lock_awb = lock; 211 + 212 + return ret; 213 + } 214 + 215 + /* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */ 216 + int m5mols_lock_3a(struct m5mols_info *info, bool lock) 217 + { 218 + int ret; 219 + 220 + ret = m5mols_lock_ae(info, lock); 221 + if (!ret) 222 + ret = m5mols_lock_awb(info, lock); 223 + /* Don't need to handle unlocking AF */ 224 + if (!ret && is_available_af(info) && lock) 225 + ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); 226 + 227 + return ret; 228 + } 229 + 230 + /* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */ 231 + int m5mols_set_ctrl(struct v4l2_ctrl *ctrl) 232 + { 233 + struct v4l2_subdev *sd = to_sd(ctrl); 234 + struct m5mols_info *info = to_m5mols(sd); 235 + int ret; 236 + 237 + switch (ctrl->id) { 238 + case V4L2_CID_ZOOM_ABSOLUTE: 239 + return m5mols_write(sd, MON_ZOOM, ctrl->val); 240 + 241 + case V4L2_CID_EXPOSURE_AUTO: 242 + ret = m5mols_lock_ae(info, 243 + ctrl->val == V4L2_EXPOSURE_AUTO ? false : true); 244 + if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO) 245 + ret = m5mols_write(sd, AE_MODE, REG_AE_ALL); 246 + if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) { 247 + int val = info->exposure->val; 248 + ret = m5mols_write(sd, AE_MODE, REG_AE_OFF); 249 + if (!ret) 250 + ret = m5mols_write(sd, AE_MAN_GAIN_MON, val); 251 + if (!ret) 252 + ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val); 253 + } 254 + return ret; 255 + 256 + case V4L2_CID_AUTO_WHITE_BALANCE: 257 + ret = m5mols_lock_awb(info, ctrl->val ? false : true); 258 + if (!ret) 259 + ret = m5mols_write(sd, AWB_MODE, ctrl->val ? 260 + REG_AWB_AUTO : REG_AWB_PRESET); 261 + return ret; 262 + 263 + case V4L2_CID_SATURATION: 264 + ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val); 265 + if (!ret) 266 + ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON); 267 + return ret; 268 + 269 + case V4L2_CID_COLORFX: 270 + /* 271 + * This control uses two kinds of registers: normal & color. 272 + * The normal effect belongs to category 1, while the color 273 + * one belongs to category 2. 274 + * 275 + * The normal effect uses one register: CAT1_EFFECT. 276 + * The color effect uses three registers: 277 + * CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB. 278 + */ 279 + ret = m5mols_write(sd, PARM_EFFECT, 280 + ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA : 281 + ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS : 282 + REG_EFFECT_OFF); 283 + if (!ret) 284 + ret = m5mols_write(sd, MON_EFFECT, 285 + ctrl->val == V4L2_COLORFX_SEPIA ? 286 + REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF); 287 + if (!ret) 288 + ret = m5mols_write(sd, MON_CFIXR, 289 + ctrl->val == V4L2_COLORFX_SEPIA ? 290 + REG_CFIXR_SEPIA : 0); 291 + if (!ret) 292 + ret = m5mols_write(sd, MON_CFIXB, 293 + ctrl->val == V4L2_COLORFX_SEPIA ? 294 + REG_CFIXB_SEPIA : 0); 295 + return ret; 296 + } 297 + 298 + return -EINVAL; 299 + }
+1004
drivers/media/video/m5mols/m5mols_core.c
··· 1 + /* 2 + * Driver for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #include <linux/i2c.h> 17 + #include <linux/slab.h> 18 + #include <linux/irq.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/delay.h> 21 + #include <linux/version.h> 22 + #include <linux/gpio.h> 23 + #include <linux/regulator/consumer.h> 24 + #include <linux/videodev2.h> 25 + #include <media/v4l2-ctrls.h> 26 + #include <media/v4l2-device.h> 27 + #include <media/v4l2-subdev.h> 28 + #include <media/m5mols.h> 29 + 30 + #include "m5mols.h" 31 + #include "m5mols_reg.h" 32 + 33 + int m5mols_debug; 34 + module_param(m5mols_debug, int, 0644); 35 + 36 + #define MODULE_NAME "M5MOLS" 37 + #define M5MOLS_I2C_CHECK_RETRY 500 38 + 39 + /* The regulator consumer names for external voltage regulators */ 40 + static struct regulator_bulk_data supplies[] = { 41 + { 42 + .supply = "core", /* ARM core power, 1.2V */ 43 + }, { 44 + .supply = "dig_18", /* digital power 1, 1.8V */ 45 + }, { 46 + .supply = "d_sensor", /* sensor power 1, 1.8V */ 47 + }, { 48 + .supply = "dig_28", /* digital power 2, 2.8V */ 49 + }, { 50 + .supply = "a_sensor", /* analog power */ 51 + }, { 52 + .supply = "dig_12", /* digital power 3, 1.2V */ 53 + }, 54 + }; 55 + 56 + static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = { 57 + [M5MOLS_RESTYPE_MONITOR] = { 58 + .width = 1920, 59 + .height = 1080, 60 + .code = V4L2_MBUS_FMT_VYUY8_2X8, 61 + .field = V4L2_FIELD_NONE, 62 + .colorspace = V4L2_COLORSPACE_JPEG, 63 + }, 64 + [M5MOLS_RESTYPE_CAPTURE] = { 65 + .width = 1920, 66 + .height = 1080, 67 + .code = V4L2_MBUS_FMT_JPEG_1X8, 68 + .field = V4L2_FIELD_NONE, 69 + .colorspace = V4L2_COLORSPACE_JPEG, 70 + }, 71 + }; 72 + #define SIZE_DEFAULT_FFMT ARRAY_SIZE(m5mols_default_ffmt) 73 + 74 + static const struct m5mols_resolution m5mols_reg_res[] = { 75 + { 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 }, /* SUB-QCIF */ 76 + { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 }, /* QQVGA */ 77 + { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 }, /* QCIF */ 78 + { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 }, 79 + { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 }, /* QVGA */ 80 + { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 }, /* QVGA */ 81 + { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 }, /* WQVGA */ 82 + { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 }, /* WQVGA */ 83 + { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 }, /* CIF */ 84 + { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 }, 85 + { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 }, /* qHD */ 86 + { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 }, /* VGA */ 87 + { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 }, 88 + { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 }, /* WVGA */ 89 + { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 }, /* SVGA */ 90 + { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 }, /* HD */ 91 + { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 }, /* 1080p */ 92 + { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 }, /* 2.63fps 8M */ 93 + { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 }, /* AHS_MON debug */ 94 + 95 + { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 }, /* QVGA */ 96 + { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 }, /* WQVGA */ 97 + { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 }, 98 + { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 }, /* qHD */ 99 + { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 }, /* VGA */ 100 + { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 }, /* WVGA */ 101 + { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 }, /* HD */ 102 + { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 }, /* 1M */ 103 + { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 }, /* 2M */ 104 + { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 }, /* Full-HD */ 105 + { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 }, /* 3Mega */ 106 + { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 }, 107 + { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 }, /* 4Mega */ 108 + { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 }, 109 + { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 }, /* 5Mega */ 110 + { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 }, /* 6Mega */ 111 + { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 }, 112 + { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 }, /* 8Mega */ 113 + }; 114 + 115 + /** 116 + * m5mols_swap_byte - an byte array to integer conversion function 117 + * @size: size in bytes of I2C packet defined in the M-5MOLS datasheet 118 + * 119 + * Convert I2C data byte array with performing any required byte 120 + * reordering to assure proper values for each data type, regardless 121 + * of the architecture endianness. 122 + */ 123 + static u32 m5mols_swap_byte(u8 *data, u8 length) 124 + { 125 + if (length == 1) 126 + return *data; 127 + else if (length == 2) 128 + return be16_to_cpu(*((u16 *)data)); 129 + else 130 + return be32_to_cpu(*((u32 *)data)); 131 + } 132 + 133 + /** 134 + * m5mols_read - I2C read function 135 + * @reg: combination of size, category and command for the I2C packet 136 + * @val: read value 137 + */ 138 + int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val) 139 + { 140 + struct i2c_client *client = v4l2_get_subdevdata(sd); 141 + u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1]; 142 + u8 size = I2C_SIZE(reg); 143 + u8 category = I2C_CATEGORY(reg); 144 + u8 cmd = I2C_COMMAND(reg); 145 + struct i2c_msg msg[2]; 146 + u8 wbuf[5]; 147 + int ret; 148 + 149 + if (!client->adapter) 150 + return -ENODEV; 151 + 152 + if (size != 1 && size != 2 && size != 4) { 153 + v4l2_err(sd, "Wrong data size\n"); 154 + return -EINVAL; 155 + } 156 + 157 + msg[0].addr = client->addr; 158 + msg[0].flags = 0; 159 + msg[0].len = 5; 160 + msg[0].buf = wbuf; 161 + wbuf[0] = 5; 162 + wbuf[1] = M5MOLS_BYTE_READ; 163 + wbuf[2] = category; 164 + wbuf[3] = cmd; 165 + wbuf[4] = size; 166 + 167 + msg[1].addr = client->addr; 168 + msg[1].flags = I2C_M_RD; 169 + msg[1].len = size + 1; 170 + msg[1].buf = rbuf; 171 + 172 + /* minimum stabilization time */ 173 + usleep_range(200, 200); 174 + 175 + ret = i2c_transfer(client->adapter, msg, 2); 176 + if (ret < 0) { 177 + v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n", 178 + size, category, cmd, ret); 179 + return ret; 180 + } 181 + 182 + *val = m5mols_swap_byte(&rbuf[1], size); 183 + 184 + return 0; 185 + } 186 + 187 + /** 188 + * m5mols_write - I2C command write function 189 + * @reg: combination of size, category and command for the I2C packet 190 + * @val: value to write 191 + */ 192 + int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) 193 + { 194 + struct i2c_client *client = v4l2_get_subdevdata(sd); 195 + u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4]; 196 + u8 category = I2C_CATEGORY(reg); 197 + u8 cmd = I2C_COMMAND(reg); 198 + u8 size = I2C_SIZE(reg); 199 + u32 *buf = (u32 *)&wbuf[4]; 200 + struct i2c_msg msg[1]; 201 + int ret; 202 + 203 + if (!client->adapter) 204 + return -ENODEV; 205 + 206 + if (size != 1 && size != 2 && size != 4) { 207 + v4l2_err(sd, "Wrong data size\n"); 208 + return -EINVAL; 209 + } 210 + 211 + msg->addr = client->addr; 212 + msg->flags = 0; 213 + msg->len = (u16)size + 4; 214 + msg->buf = wbuf; 215 + wbuf[0] = size + 4; 216 + wbuf[1] = M5MOLS_BYTE_WRITE; 217 + wbuf[2] = category; 218 + wbuf[3] = cmd; 219 + 220 + *buf = m5mols_swap_byte((u8 *)&val, size); 221 + 222 + usleep_range(200, 200); 223 + 224 + ret = i2c_transfer(client->adapter, msg, 1); 225 + if (ret < 0) { 226 + v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n", 227 + size, category, cmd, ret); 228 + return ret; 229 + } 230 + 231 + return 0; 232 + } 233 + 234 + int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask) 235 + { 236 + u32 busy, i; 237 + int ret; 238 + 239 + for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { 240 + ret = m5mols_read(sd, I2C_REG(category, cmd, 1), &busy); 241 + if (ret < 0) 242 + return ret; 243 + if ((busy & mask) == mask) 244 + return 0; 245 + } 246 + return -EBUSY; 247 + } 248 + 249 + /** 250 + * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts 251 + * 252 + * Before writing desired interrupt value the INT_FACTOR register should 253 + * be read to clear pending interrupts. 254 + */ 255 + int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg) 256 + { 257 + struct m5mols_info *info = to_m5mols(sd); 258 + u32 mask = is_available_af(info) ? REG_INT_AF : 0; 259 + u32 dummy; 260 + int ret; 261 + 262 + ret = m5mols_read(sd, SYSTEM_INT_FACTOR, &dummy); 263 + if (!ret) 264 + ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask); 265 + return ret; 266 + } 267 + 268 + /** 269 + * m5mols_reg_mode - Write the mode and check busy status 270 + * 271 + * It always accompanies a little delay changing the M-5MOLS mode, so it is 272 + * needed checking current busy status to guarantee right mode. 273 + */ 274 + static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode) 275 + { 276 + int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); 277 + 278 + return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode); 279 + } 280 + 281 + /** 282 + * m5mols_mode - manage the M-5MOLS's mode 283 + * @mode: the required operation mode 284 + * 285 + * The commands of M-5MOLS are grouped into specific modes. Each functionality 286 + * can be guaranteed only when the sensor is operating in mode which which 287 + * a command belongs to. 288 + */ 289 + int m5mols_mode(struct m5mols_info *info, u32 mode) 290 + { 291 + struct v4l2_subdev *sd = &info->sd; 292 + int ret = -EINVAL; 293 + u32 reg; 294 + 295 + if (mode < REG_PARAMETER && mode > REG_CAPTURE) 296 + return ret; 297 + 298 + ret = m5mols_read(sd, SYSTEM_SYSMODE, &reg); 299 + if ((!ret && reg == mode) || ret) 300 + return ret; 301 + 302 + switch (reg) { 303 + case REG_PARAMETER: 304 + ret = m5mols_reg_mode(sd, REG_MONITOR); 305 + if (!ret && mode == REG_MONITOR) 306 + break; 307 + if (!ret) 308 + ret = m5mols_reg_mode(sd, REG_CAPTURE); 309 + break; 310 + 311 + case REG_MONITOR: 312 + if (mode == REG_PARAMETER) { 313 + ret = m5mols_reg_mode(sd, REG_PARAMETER); 314 + break; 315 + } 316 + 317 + ret = m5mols_reg_mode(sd, REG_CAPTURE); 318 + break; 319 + 320 + case REG_CAPTURE: 321 + ret = m5mols_reg_mode(sd, REG_MONITOR); 322 + if (!ret && mode == REG_MONITOR) 323 + break; 324 + if (!ret) 325 + ret = m5mols_reg_mode(sd, REG_PARAMETER); 326 + break; 327 + 328 + default: 329 + v4l2_warn(sd, "Wrong mode: %d\n", mode); 330 + } 331 + 332 + if (!ret) 333 + info->mode = mode; 334 + 335 + return ret; 336 + } 337 + 338 + /** 339 + * m5mols_get_version - retrieve full revisions information of M-5MOLS 340 + * 341 + * The version information includes revisions of hardware and firmware, 342 + * AutoFocus alghorithm version and the version string. 343 + */ 344 + static int m5mols_get_version(struct v4l2_subdev *sd) 345 + { 346 + struct m5mols_info *info = to_m5mols(sd); 347 + union { 348 + struct m5mols_version ver; 349 + u8 bytes[VERSION_SIZE]; 350 + } version; 351 + u32 *value; 352 + u8 cmd = CAT0_VER_CUSTOMER; 353 + int ret; 354 + 355 + do { 356 + value = (u32 *)&version.bytes[cmd]; 357 + ret = m5mols_read(sd, SYSTEM_CMD(cmd), value); 358 + if (ret) 359 + return ret; 360 + } while (cmd++ != CAT0_VER_AWB); 361 + 362 + do { 363 + value = (u32 *)&version.bytes[cmd]; 364 + ret = m5mols_read(sd, SYSTEM_VER_STRING, value); 365 + if (ret) 366 + return ret; 367 + if (cmd >= VERSION_SIZE - 1) 368 + return -EINVAL; 369 + } while (version.bytes[cmd++]); 370 + 371 + value = (u32 *)&version.bytes[cmd]; 372 + ret = m5mols_read(sd, AF_VERSION, value); 373 + if (ret) 374 + return ret; 375 + 376 + /* store version information swapped for being readable */ 377 + info->ver = version.ver; 378 + info->ver.fw = be16_to_cpu(info->ver.fw); 379 + info->ver.hw = be16_to_cpu(info->ver.hw); 380 + info->ver.param = be16_to_cpu(info->ver.param); 381 + info->ver.awb = be16_to_cpu(info->ver.awb); 382 + 383 + v4l2_info(sd, "Manufacturer\t[%s]\n", 384 + is_manufacturer(info, REG_SAMSUNG_ELECTRO) ? 385 + "Samsung Electro-Machanics" : 386 + is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 387 + "Samsung Fiber-Optics" : 388 + is_manufacturer(info, REG_SAMSUNG_TECHWIN) ? 389 + "Samsung Techwin" : "None"); 390 + v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n", 391 + info->ver.customer, info->ver.project); 392 + 393 + if (!is_available_af(info)) 394 + v4l2_info(sd, "No support Auto Focus on this firmware\n"); 395 + 396 + return ret; 397 + } 398 + 399 + /** 400 + * __find_restype - Lookup M-5MOLS resolution type according to pixel code 401 + * @code: pixel code 402 + */ 403 + static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code) 404 + { 405 + enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR; 406 + 407 + do { 408 + if (code == m5mols_default_ffmt[type].code) 409 + return type; 410 + } while (type++ != SIZE_DEFAULT_FFMT); 411 + 412 + return 0; 413 + } 414 + 415 + /** 416 + * __find_resolution - Lookup preset and type of M-5MOLS's resolution 417 + * @mf: pixel format to find/negotiate the resolution preset for 418 + * @type: M-5MOLS resolution type 419 + * @resolution: M-5MOLS resolution preset register value 420 + * 421 + * Find nearest resolution matching resolution preset and adjust mf 422 + * to supported values. 423 + */ 424 + static int __find_resolution(struct v4l2_subdev *sd, 425 + struct v4l2_mbus_framefmt *mf, 426 + enum m5mols_restype *type, 427 + u32 *resolution) 428 + { 429 + const struct m5mols_resolution *fsize = &m5mols_reg_res[0]; 430 + const struct m5mols_resolution *match = NULL; 431 + enum m5mols_restype stype = __find_restype(mf->code); 432 + int i = ARRAY_SIZE(m5mols_reg_res); 433 + unsigned int min_err = ~0; 434 + 435 + while (i--) { 436 + int err; 437 + if (stype == fsize->type) { 438 + err = abs(fsize->width - mf->width) 439 + + abs(fsize->height - mf->height); 440 + 441 + if (err < min_err) { 442 + min_err = err; 443 + match = fsize; 444 + } 445 + } 446 + fsize++; 447 + } 448 + if (match) { 449 + mf->width = match->width; 450 + mf->height = match->height; 451 + *resolution = match->reg; 452 + *type = stype; 453 + return 0; 454 + } 455 + 456 + return -EINVAL; 457 + } 458 + 459 + static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info, 460 + struct v4l2_subdev_fh *fh, 461 + enum v4l2_subdev_format_whence which, 462 + enum m5mols_restype type) 463 + { 464 + if (which == V4L2_SUBDEV_FORMAT_TRY) 465 + return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL; 466 + 467 + return &info->ffmt[type]; 468 + } 469 + 470 + static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, 471 + struct v4l2_subdev_format *fmt) 472 + { 473 + struct m5mols_info *info = to_m5mols(sd); 474 + struct v4l2_mbus_framefmt *format; 475 + 476 + if (fmt->pad != 0) 477 + return -EINVAL; 478 + 479 + format = __find_format(info, fh, fmt->which, info->res_type); 480 + if (!format) 481 + return -EINVAL; 482 + 483 + fmt->format = *format; 484 + return 0; 485 + } 486 + 487 + static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, 488 + struct v4l2_subdev_format *fmt) 489 + { 490 + struct m5mols_info *info = to_m5mols(sd); 491 + struct v4l2_mbus_framefmt *format = &fmt->format; 492 + struct v4l2_mbus_framefmt *sfmt; 493 + enum m5mols_restype type; 494 + u32 resolution = 0; 495 + int ret; 496 + 497 + if (fmt->pad != 0) 498 + return -EINVAL; 499 + 500 + ret = __find_resolution(sd, format, &type, &resolution); 501 + if (ret < 0) 502 + return ret; 503 + 504 + sfmt = __find_format(info, fh, fmt->which, type); 505 + if (!sfmt) 506 + return 0; 507 + 508 + *sfmt = m5mols_default_ffmt[type]; 509 + sfmt->width = format->width; 510 + sfmt->height = format->height; 511 + 512 + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 513 + info->resolution = resolution; 514 + info->code = format->code; 515 + info->res_type = type; 516 + } 517 + 518 + return 0; 519 + } 520 + 521 + static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, 522 + struct v4l2_subdev_fh *fh, 523 + struct v4l2_subdev_mbus_code_enum *code) 524 + { 525 + if (!code || code->index >= SIZE_DEFAULT_FFMT) 526 + return -EINVAL; 527 + 528 + code->code = m5mols_default_ffmt[code->index].code; 529 + 530 + return 0; 531 + } 532 + 533 + static struct v4l2_subdev_pad_ops m5mols_pad_ops = { 534 + .enum_mbus_code = m5mols_enum_mbus_code, 535 + .get_fmt = m5mols_get_fmt, 536 + .set_fmt = m5mols_set_fmt, 537 + }; 538 + 539 + /** 540 + * m5mols_sync_controls - Apply default scene mode and the current controls 541 + * 542 + * This is used only streaming for syncing between v4l2_ctrl framework and 543 + * m5mols's controls. First, do the scenemode to the sensor, then call 544 + * v4l2_ctrl_handler_setup. It can be same between some commands and 545 + * the scenemode's in the default v4l2_ctrls. But, such commands of control 546 + * should be prior to the scenemode's one. 547 + */ 548 + int m5mols_sync_controls(struct m5mols_info *info) 549 + { 550 + int ret = -EINVAL; 551 + 552 + if (!is_ctrl_synced(info)) { 553 + ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); 554 + if (ret) 555 + return ret; 556 + 557 + v4l2_ctrl_handler_setup(&info->handle); 558 + info->ctrl_sync = true; 559 + } 560 + 561 + return ret; 562 + } 563 + 564 + /** 565 + * m5mols_start_monitor - Start the monitor mode 566 + * 567 + * Before applying the controls setup the resolution and frame rate 568 + * in PARAMETER mode, and then switch over to MONITOR mode. 569 + */ 570 + static int m5mols_start_monitor(struct m5mols_info *info) 571 + { 572 + struct v4l2_subdev *sd = &info->sd; 573 + int ret; 574 + 575 + ret = m5mols_mode(info, REG_PARAMETER); 576 + if (!ret) 577 + ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution); 578 + if (!ret) 579 + ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30); 580 + if (!ret) 581 + ret = m5mols_mode(info, REG_MONITOR); 582 + if (!ret) 583 + ret = m5mols_sync_controls(info); 584 + 585 + return ret; 586 + } 587 + 588 + static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) 589 + { 590 + struct m5mols_info *info = to_m5mols(sd); 591 + 592 + if (enable) { 593 + int ret = -EINVAL; 594 + 595 + if (is_code(info->code, M5MOLS_RESTYPE_MONITOR)) 596 + ret = m5mols_start_monitor(info); 597 + if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE)) 598 + ret = m5mols_start_capture(info); 599 + 600 + return ret; 601 + } 602 + 603 + return m5mols_mode(info, REG_PARAMETER); 604 + } 605 + 606 + static const struct v4l2_subdev_video_ops m5mols_video_ops = { 607 + .s_stream = m5mols_s_stream, 608 + }; 609 + 610 + static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) 611 + { 612 + struct v4l2_subdev *sd = to_sd(ctrl); 613 + struct m5mols_info *info = to_m5mols(sd); 614 + int ret; 615 + 616 + info->mode_save = info->mode; 617 + 618 + ret = m5mols_mode(info, REG_PARAMETER); 619 + if (!ret) 620 + ret = m5mols_set_ctrl(ctrl); 621 + if (!ret) 622 + ret = m5mols_mode(info, info->mode_save); 623 + 624 + return ret; 625 + } 626 + 627 + static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { 628 + .s_ctrl = m5mols_s_ctrl, 629 + }; 630 + 631 + static int m5mols_sensor_power(struct m5mols_info *info, bool enable) 632 + { 633 + struct v4l2_subdev *sd = &info->sd; 634 + struct i2c_client *client = v4l2_get_subdevdata(sd); 635 + const struct m5mols_platform_data *pdata = info->pdata; 636 + int ret; 637 + 638 + if (enable) { 639 + if (is_powered(info)) 640 + return 0; 641 + 642 + if (info->set_power) { 643 + ret = info->set_power(&client->dev, 1); 644 + if (ret) 645 + return ret; 646 + } 647 + 648 + ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); 649 + if (ret) { 650 + info->set_power(&client->dev, 0); 651 + return ret; 652 + } 653 + 654 + gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity); 655 + usleep_range(1000, 1000); 656 + info->power = true; 657 + 658 + return ret; 659 + } 660 + 661 + if (!is_powered(info)) 662 + return 0; 663 + 664 + ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); 665 + if (ret) 666 + return ret; 667 + 668 + if (info->set_power) 669 + info->set_power(&client->dev, 0); 670 + 671 + gpio_set_value(pdata->gpio_reset, pdata->reset_polarity); 672 + usleep_range(1000, 1000); 673 + info->power = false; 674 + 675 + return ret; 676 + } 677 + 678 + /* m5mols_update_fw - optional firmware update routine */ 679 + int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd, 680 + int (*set_power)(struct m5mols_info *, bool)) 681 + { 682 + return 0; 683 + } 684 + 685 + /** 686 + * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core. 687 + * 688 + * Booting internal ARM core makes the M-5MOLS is ready for getting commands 689 + * with I2C. It's the first thing to be done after it powered up. It must wait 690 + * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting. 691 + */ 692 + static int m5mols_sensor_armboot(struct v4l2_subdev *sd) 693 + { 694 + int ret; 695 + 696 + ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); 697 + if (ret < 0) 698 + return ret; 699 + 700 + msleep(520); 701 + 702 + ret = m5mols_get_version(sd); 703 + if (!ret) 704 + ret = m5mols_update_fw(sd, m5mols_sensor_power); 705 + if (ret) 706 + return ret; 707 + 708 + v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n"); 709 + 710 + ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI); 711 + if (!ret) 712 + ret = m5mols_enable_interrupt(sd, REG_INT_AF); 713 + 714 + return ret; 715 + } 716 + 717 + static int m5mols_init_controls(struct m5mols_info *info) 718 + { 719 + struct v4l2_subdev *sd = &info->sd; 720 + u16 max_exposure; 721 + u16 step_zoom; 722 + int ret; 723 + 724 + /* Determine value's range & step of controls for various FW version */ 725 + ret = m5mols_read(sd, AE_MAX_GAIN_MON, (u32 *)&max_exposure); 726 + if (!ret) 727 + step_zoom = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1; 728 + if (ret) 729 + return ret; 730 + 731 + v4l2_ctrl_handler_init(&info->handle, 6); 732 + info->autowb = v4l2_ctrl_new_std(&info->handle, 733 + &m5mols_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, 734 + 0, 1, 1, 0); 735 + info->saturation = v4l2_ctrl_new_std(&info->handle, 736 + &m5mols_ctrl_ops, V4L2_CID_SATURATION, 737 + 1, 5, 1, 3); 738 + info->zoom = v4l2_ctrl_new_std(&info->handle, 739 + &m5mols_ctrl_ops, V4L2_CID_ZOOM_ABSOLUTE, 740 + 1, 70, step_zoom, 1); 741 + info->exposure = v4l2_ctrl_new_std(&info->handle, 742 + &m5mols_ctrl_ops, V4L2_CID_EXPOSURE, 743 + 0, max_exposure, 1, (int)max_exposure/2); 744 + info->colorfx = v4l2_ctrl_new_std_menu(&info->handle, 745 + &m5mols_ctrl_ops, V4L2_CID_COLORFX, 746 + 4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE); 747 + info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle, 748 + &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 749 + 1, 0, V4L2_EXPOSURE_MANUAL); 750 + 751 + sd->ctrl_handler = &info->handle; 752 + if (info->handle.error) { 753 + v4l2_err(sd, "Failed to initialize controls: %d\n", ret); 754 + v4l2_ctrl_handler_free(&info->handle); 755 + return info->handle.error; 756 + } 757 + 758 + v4l2_ctrl_cluster(2, &info->autoexposure); 759 + 760 + return 0; 761 + } 762 + 763 + /** 764 + * m5mols_s_power - Main sensor power control function 765 + * 766 + * To prevent breaking the lens when the sensor is powered off the Soft-Landing 767 + * algorithm is called where available. The Soft-Landing algorithm availability 768 + * dependends on the firmware provider. 769 + */ 770 + static int m5mols_s_power(struct v4l2_subdev *sd, int on) 771 + { 772 + struct m5mols_info *info = to_m5mols(sd); 773 + int ret; 774 + 775 + if (on) { 776 + ret = m5mols_sensor_power(info, true); 777 + if (!ret) 778 + ret = m5mols_sensor_armboot(sd); 779 + if (!ret) 780 + ret = m5mols_init_controls(info); 781 + if (ret) 782 + return ret; 783 + 784 + info->ffmt[M5MOLS_RESTYPE_MONITOR] = 785 + m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR]; 786 + info->ffmt[M5MOLS_RESTYPE_CAPTURE] = 787 + m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE]; 788 + return ret; 789 + } 790 + 791 + if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { 792 + ret = m5mols_mode(info, REG_MONITOR); 793 + if (!ret) 794 + ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP); 795 + if (!ret) 796 + ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); 797 + if (!ret) 798 + ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS, 799 + REG_AF_IDLE); 800 + if (!ret) 801 + v4l2_info(sd, "Success soft-landing lens\n"); 802 + } 803 + 804 + ret = m5mols_sensor_power(info, false); 805 + if (!ret) { 806 + v4l2_ctrl_handler_free(&info->handle); 807 + info->ctrl_sync = false; 808 + } 809 + 810 + return ret; 811 + } 812 + 813 + static int m5mols_log_status(struct v4l2_subdev *sd) 814 + { 815 + struct m5mols_info *info = to_m5mols(sd); 816 + 817 + v4l2_ctrl_handler_log_status(&info->handle, sd->name); 818 + 819 + return 0; 820 + } 821 + 822 + static const struct v4l2_subdev_core_ops m5mols_core_ops = { 823 + .s_power = m5mols_s_power, 824 + .g_ctrl = v4l2_subdev_g_ctrl, 825 + .s_ctrl = v4l2_subdev_s_ctrl, 826 + .queryctrl = v4l2_subdev_queryctrl, 827 + .querymenu = v4l2_subdev_querymenu, 828 + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, 829 + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, 830 + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, 831 + .log_status = m5mols_log_status, 832 + }; 833 + 834 + static const struct v4l2_subdev_ops m5mols_ops = { 835 + .core = &m5mols_core_ops, 836 + .pad = &m5mols_pad_ops, 837 + .video = &m5mols_video_ops, 838 + }; 839 + 840 + static void m5mols_irq_work(struct work_struct *work) 841 + { 842 + struct m5mols_info *info = 843 + container_of(work, struct m5mols_info, work_irq); 844 + struct v4l2_subdev *sd = &info->sd; 845 + u32 reg; 846 + int ret; 847 + 848 + if (!is_powered(info) || 849 + m5mols_read(sd, SYSTEM_INT_FACTOR, &info->interrupt)) 850 + return; 851 + 852 + switch (info->interrupt & REG_INT_MASK) { 853 + case REG_INT_AF: 854 + if (!is_available_af(info)) 855 + break; 856 + ret = m5mols_read(sd, AF_STATUS, &reg); 857 + v4l2_dbg(2, m5mols_debug, sd, "AF %s\n", 858 + reg == REG_AF_FAIL ? "Failed" : 859 + reg == REG_AF_SUCCESS ? "Success" : 860 + reg == REG_AF_IDLE ? "Idle" : "Busy"); 861 + break; 862 + case REG_INT_CAPTURE: 863 + if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags)) 864 + wake_up_interruptible(&info->irq_waitq); 865 + 866 + v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n"); 867 + break; 868 + default: 869 + v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg); 870 + break; 871 + }; 872 + } 873 + 874 + static irqreturn_t m5mols_irq_handler(int irq, void *data) 875 + { 876 + struct v4l2_subdev *sd = data; 877 + struct m5mols_info *info = to_m5mols(sd); 878 + 879 + schedule_work(&info->work_irq); 880 + 881 + return IRQ_HANDLED; 882 + } 883 + 884 + static int __devinit m5mols_probe(struct i2c_client *client, 885 + const struct i2c_device_id *id) 886 + { 887 + const struct m5mols_platform_data *pdata = client->dev.platform_data; 888 + struct m5mols_info *info; 889 + struct v4l2_subdev *sd; 890 + int ret; 891 + 892 + if (pdata == NULL) { 893 + dev_err(&client->dev, "No platform data\n"); 894 + return -EINVAL; 895 + } 896 + 897 + if (!gpio_is_valid(pdata->gpio_reset)) { 898 + dev_err(&client->dev, "No valid RESET GPIO specified\n"); 899 + return -EINVAL; 900 + } 901 + 902 + if (!pdata->irq) { 903 + dev_err(&client->dev, "Interrupt not assigned\n"); 904 + return -EINVAL; 905 + } 906 + 907 + info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL); 908 + if (!info) 909 + return -ENOMEM; 910 + 911 + info->pdata = pdata; 912 + info->set_power = pdata->set_power; 913 + 914 + ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST"); 915 + if (ret) { 916 + dev_err(&client->dev, "Failed to request gpio: %d\n", ret); 917 + goto out_free; 918 + } 919 + gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity); 920 + 921 + ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); 922 + if (ret) { 923 + dev_err(&client->dev, "Failed to get regulators: %d\n", ret); 924 + goto out_gpio; 925 + } 926 + 927 + sd = &info->sd; 928 + strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); 929 + v4l2_i2c_subdev_init(sd, client, &m5mols_ops); 930 + 931 + info->pad.flags = MEDIA_PAD_FL_SOURCE; 932 + ret = media_entity_init(&sd->entity, 1, &info->pad, 0); 933 + if (ret < 0) 934 + goto out_reg; 935 + sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; 936 + 937 + init_waitqueue_head(&info->irq_waitq); 938 + INIT_WORK(&info->work_irq, m5mols_irq_work); 939 + ret = request_irq(pdata->irq, m5mols_irq_handler, 940 + IRQF_TRIGGER_RISING, MODULE_NAME, sd); 941 + if (ret) { 942 + dev_err(&client->dev, "Interrupt request failed: %d\n", ret); 943 + goto out_me; 944 + } 945 + info->res_type = M5MOLS_RESTYPE_MONITOR; 946 + return 0; 947 + out_me: 948 + media_entity_cleanup(&sd->entity); 949 + out_reg: 950 + regulator_bulk_free(ARRAY_SIZE(supplies), supplies); 951 + out_gpio: 952 + gpio_free(pdata->gpio_reset); 953 + out_free: 954 + kfree(info); 955 + return ret; 956 + } 957 + 958 + static int __devexit m5mols_remove(struct i2c_client *client) 959 + { 960 + struct v4l2_subdev *sd = i2c_get_clientdata(client); 961 + struct m5mols_info *info = to_m5mols(sd); 962 + 963 + v4l2_device_unregister_subdev(sd); 964 + free_irq(info->pdata->irq, sd); 965 + 966 + regulator_bulk_free(ARRAY_SIZE(supplies), supplies); 967 + gpio_free(info->pdata->gpio_reset); 968 + media_entity_cleanup(&sd->entity); 969 + kfree(info); 970 + return 0; 971 + } 972 + 973 + static const struct i2c_device_id m5mols_id[] = { 974 + { MODULE_NAME, 0 }, 975 + { }, 976 + }; 977 + MODULE_DEVICE_TABLE(i2c, m5mols_id); 978 + 979 + static struct i2c_driver m5mols_i2c_driver = { 980 + .driver = { 981 + .name = MODULE_NAME, 982 + }, 983 + .probe = m5mols_probe, 984 + .remove = __devexit_p(m5mols_remove), 985 + .id_table = m5mols_id, 986 + }; 987 + 988 + static int __init m5mols_mod_init(void) 989 + { 990 + return i2c_add_driver(&m5mols_i2c_driver); 991 + } 992 + 993 + static void __exit m5mols_mod_exit(void) 994 + { 995 + i2c_del_driver(&m5mols_i2c_driver); 996 + } 997 + 998 + module_init(m5mols_mod_init); 999 + module_exit(m5mols_mod_exit); 1000 + 1001 + MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>"); 1002 + MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>"); 1003 + MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver"); 1004 + MODULE_LICENSE("GPL");
+399
drivers/media/video/m5mols/m5mols_reg.h
··· 1 + /* 2 + * Register map for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #ifndef M5MOLS_REG_H 17 + #define M5MOLS_REG_H 18 + 19 + #define M5MOLS_I2C_MAX_SIZE 4 20 + #define M5MOLS_BYTE_READ 0x01 21 + #define M5MOLS_BYTE_WRITE 0x02 22 + 23 + #define I2C_CATEGORY(__cat) ((__cat >> 16) & 0xff) 24 + #define I2C_COMMAND(__comm) ((__comm >> 8) & 0xff) 25 + #define I2C_SIZE(__reg_s) ((__reg_s) & 0xff) 26 + #define I2C_REG(__cat, __cmd, __reg_s) ((__cat << 16) | (__cmd << 8) | __reg_s) 27 + 28 + /* 29 + * Category section register 30 + * 31 + * The category means set including relevant command of M-5MOLS. 32 + */ 33 + #define CAT_SYSTEM 0x00 34 + #define CAT_PARAM 0x01 35 + #define CAT_MONITOR 0x02 36 + #define CAT_AE 0x03 37 + #define CAT_WB 0x06 38 + #define CAT_EXIF 0x07 39 + #define CAT_FD 0x09 40 + #define CAT_LENS 0x0a 41 + #define CAT_CAPT_PARM 0x0b 42 + #define CAT_CAPT_CTRL 0x0c 43 + #define CAT_FLASH 0x0f /* related to FW, revisions, booting */ 44 + 45 + /* 46 + * Category 0 - SYSTEM mode 47 + * 48 + * The SYSTEM mode in the M-5MOLS means area available to handle with the whole 49 + * & all-round system of sensor. It deals with version/interrupt/setting mode & 50 + * even sensor's status. Especially, the M-5MOLS sensor with ISP varies by 51 + * packaging & manufacturer, even the customer and project code. And the 52 + * function details may vary among them. The version information helps to 53 + * determine what methods shall be used in the driver. 54 + * 55 + * There is many registers between customer version address and awb one. For 56 + * more specific contents, see definition if file m5mols.h. 57 + */ 58 + #define CAT0_VER_CUSTOMER 0x00 /* customer version */ 59 + #define CAT0_VER_AWB 0x09 /* Auto WB version */ 60 + #define CAT0_VER_STRING 0x0a /* string including M-5MOLS */ 61 + #define CAT0_SYSMODE 0x0b /* SYSTEM mode register */ 62 + #define CAT0_STATUS 0x0c /* SYSTEM mode status register */ 63 + #define CAT0_INT_FACTOR 0x10 /* interrupt pending register */ 64 + #define CAT0_INT_ENABLE 0x11 /* interrupt enable register */ 65 + 66 + #define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1) 67 + #define REG_SYSINIT 0x00 /* SYSTEM mode */ 68 + #define REG_PARAMETER 0x01 /* PARAMETER mode */ 69 + #define REG_MONITOR 0x02 /* MONITOR mode */ 70 + #define REG_CAPTURE 0x03 /* CAPTURE mode */ 71 + 72 + #define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1) 73 + #define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1) 74 + #define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */ 75 + #define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */ 76 + #define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */ 77 + 78 + #define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1) 79 + #define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1) 80 + #define REG_INT_MODE (1 << 0) 81 + #define REG_INT_AF (1 << 1) 82 + #define REG_INT_ZOOM (1 << 2) 83 + #define REG_INT_CAPTURE (1 << 3) 84 + #define REG_INT_FRAMESYNC (1 << 4) 85 + #define REG_INT_FD (1 << 5) 86 + #define REG_INT_LENS_INIT (1 << 6) 87 + #define REG_INT_SOUND (1 << 7) 88 + #define REG_INT_MASK 0x0f 89 + 90 + /* 91 + * category 1 - PARAMETER mode 92 + * 93 + * This category supports function of camera features of M-5MOLS. It means we 94 + * can handle with preview(MONITOR) resolution size/frame per second/interface 95 + * between the sensor and the Application Processor/even the image effect. 96 + */ 97 + #define CAT1_DATA_INTERFACE 0x00 /* interface between sensor and AP */ 98 + #define CAT1_MONITOR_SIZE 0x01 /* resolution at the MONITOR mode */ 99 + #define CAT1_MONITOR_FPS 0x02 /* frame per second at this mode */ 100 + #define CAT1_EFFECT 0x0b /* image effects */ 101 + 102 + #define PARM_MON_SIZE I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1) 103 + 104 + #define PARM_MON_FPS I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1) 105 + #define REG_FPS_30 0x02 106 + 107 + #define PARM_INTERFACE I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1) 108 + #define REG_INTERFACE_MIPI 0x02 109 + 110 + #define PARM_EFFECT I2C_REG(CAT_PARAM, CAT1_EFFECT, 1) 111 + #define REG_EFFECT_OFF 0x00 112 + #define REG_EFFECT_NEGA 0x01 113 + #define REG_EFFECT_EMBOSS 0x06 114 + #define REG_EFFECT_OUTLINE 0x07 115 + #define REG_EFFECT_WATERCOLOR 0x08 116 + 117 + /* 118 + * Category 2 - MONITOR mode 119 + * 120 + * The MONITOR mode is same as preview mode as we said. The M-5MOLS has another 121 + * mode named "Preview", but this preview mode is used at the case specific 122 + * vider-recording mode. This mmode supports only YUYV format. On the other 123 + * hand, the JPEG & RAW formats is supports by CAPTURE mode. And, there are 124 + * another options like zoom/color effect(different with effect in PARAMETER 125 + * mode)/anti hand shaking algorithm. 126 + */ 127 + #define CAT2_ZOOM 0x01 /* set the zoom position & execute */ 128 + #define CAT2_ZOOM_STEP 0x03 /* set the zoom step */ 129 + #define CAT2_CFIXB 0x09 /* CB value for color effect */ 130 + #define CAT2_CFIXR 0x0a /* CR value for color effect */ 131 + #define CAT2_COLOR_EFFECT 0x0b /* set on/off of color effect */ 132 + #define CAT2_CHROMA_LVL 0x0f /* set chroma level */ 133 + #define CAT2_CHROMA_EN 0x10 /* set on/off of choroma */ 134 + #define CAT2_EDGE_LVL 0x11 /* set sharpness level */ 135 + #define CAT2_EDGE_EN 0x12 /* set on/off sharpness */ 136 + #define CAT2_TONE_CTL 0x25 /* set tone color(contrast) */ 137 + 138 + #define MON_ZOOM I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1) 139 + 140 + #define MON_CFIXR I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1) 141 + #define MON_CFIXB I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1) 142 + #define REG_CFIXB_SEPIA 0xd8 143 + #define REG_CFIXR_SEPIA 0x18 144 + 145 + #define MON_EFFECT I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1) 146 + #define REG_COLOR_EFFECT_OFF 0x00 147 + #define REG_COLOR_EFFECT_ON 0x01 148 + 149 + #define MON_CHROMA_EN I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1) 150 + #define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1) 151 + #define REG_CHROMA_OFF 0x00 152 + #define REG_CHROMA_ON 0x01 153 + 154 + #define MON_EDGE_EN I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1) 155 + #define MON_EDGE_LVL I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1) 156 + #define REG_EDGE_OFF 0x00 157 + #define REG_EDGE_ON 0x01 158 + 159 + #define MON_TONE_CTL I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1) 160 + 161 + /* 162 + * Category 3 - Auto Exposure 163 + * 164 + * The M-5MOLS exposure capbility is detailed as which is similar to digital 165 + * camera. This category supports AE locking/various AE mode(range of exposure) 166 + * /ISO/flickering/EV bias/shutter/meteoring, and anything else. And the 167 + * maximum/minimum exposure gain value depending on M-5MOLS firmware, may be 168 + * different. So, this category also provide getting the max/min values. And, 169 + * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values. 170 + */ 171 + #define CAT3_AE_LOCK 0x00 /* locking Auto exposure */ 172 + #define CAT3_AE_MODE 0x01 /* set AE mode, mode means range */ 173 + #define CAT3_ISO 0x05 /* set ISO */ 174 + #define CAT3_EV_PRESET_MONITOR 0x0a /* EV(scenemode) preset for MONITOR */ 175 + #define CAT3_EV_PRESET_CAPTURE 0x0b /* EV(scenemode) preset for CAPTURE */ 176 + #define CAT3_MANUAL_GAIN_MON 0x12 /* meteoring value for the MONITOR */ 177 + #define CAT3_MAX_GAIN_MON 0x1a /* max gain value for the MONITOR */ 178 + #define CAT3_MANUAL_GAIN_CAP 0x26 /* meteoring value for the CAPTURE */ 179 + #define CAT3_AE_INDEX 0x38 /* AE index */ 180 + 181 + #define AE_LOCK I2C_REG(CAT_AE, CAT3_AE_LOCK, 1) 182 + #define REG_AE_UNLOCK 0x00 183 + #define REG_AE_LOCK 0x01 184 + 185 + #define AE_MODE I2C_REG(CAT_AE, CAT3_AE_MODE, 1) 186 + #define REG_AE_OFF 0x00 /* AE off */ 187 + #define REG_AE_ALL 0x01 /* calc AE in all block integral */ 188 + #define REG_AE_CENTER 0x03 /* calc AE in center weighted */ 189 + #define REG_AE_SPOT 0x06 /* calc AE in specific spot */ 190 + 191 + #define AE_ISO I2C_REG(CAT_AE, CAT3_ISO, 1) 192 + #define REG_ISO_AUTO 0x00 193 + #define REG_ISO_50 0x01 194 + #define REG_ISO_100 0x02 195 + #define REG_ISO_200 0x03 196 + #define REG_ISO_400 0x04 197 + #define REG_ISO_800 0x05 198 + 199 + #define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1) 200 + #define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1) 201 + #define REG_SCENE_NORMAL 0x00 202 + #define REG_SCENE_PORTRAIT 0x01 203 + #define REG_SCENE_LANDSCAPE 0x02 204 + #define REG_SCENE_SPORTS 0x03 205 + #define REG_SCENE_PARTY_INDOOR 0x04 206 + #define REG_SCENE_BEACH_SNOW 0x05 207 + #define REG_SCENE_SUNSET 0x06 208 + #define REG_SCENE_DAWN_DUSK 0x07 209 + #define REG_SCENE_FALL 0x08 210 + #define REG_SCENE_NIGHT 0x09 211 + #define REG_SCENE_AGAINST_LIGHT 0x0a 212 + #define REG_SCENE_FIRE 0x0b 213 + #define REG_SCENE_TEXT 0x0c 214 + #define REG_SCENE_CANDLE 0x0d 215 + 216 + #define AE_MAN_GAIN_MON I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2) 217 + #define AE_MAX_GAIN_MON I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2) 218 + #define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2) 219 + 220 + #define AE_INDEX I2C_REG(CAT_AE, CAT3_AE_INDEX, 1) 221 + #define REG_AE_INDEX_20_NEG 0x00 222 + #define REG_AE_INDEX_15_NEG 0x01 223 + #define REG_AE_INDEX_10_NEG 0x02 224 + #define REG_AE_INDEX_05_NEG 0x03 225 + #define REG_AE_INDEX_00 0x04 226 + #define REG_AE_INDEX_05_POS 0x05 227 + #define REG_AE_INDEX_10_POS 0x06 228 + #define REG_AE_INDEX_15_POS 0x07 229 + #define REG_AE_INDEX_20_POS 0x08 230 + 231 + /* 232 + * Category 6 - White Balance 233 + * 234 + * This category provide AWB locking/mode/preset/speed/gain bias, etc. 235 + */ 236 + #define CAT6_AWB_LOCK 0x00 /* locking Auto Whitebalance */ 237 + #define CAT6_AWB_MODE 0x02 /* set Auto or Manual */ 238 + #define CAT6_AWB_MANUAL 0x03 /* set Manual(preset) value */ 239 + 240 + #define AWB_LOCK I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1) 241 + #define REG_AWB_UNLOCK 0x00 242 + #define REG_AWB_LOCK 0x01 243 + 244 + #define AWB_MODE I2C_REG(CAT_WB, CAT6_AWB_MODE, 1) 245 + #define REG_AWB_AUTO 0x01 /* AWB off */ 246 + #define REG_AWB_PRESET 0x02 /* AWB preset */ 247 + 248 + #define AWB_MANUAL I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1) 249 + #define REG_AWB_INCANDESCENT 0x01 250 + #define REG_AWB_FLUORESCENT_1 0x02 251 + #define REG_AWB_FLUORESCENT_2 0x03 252 + #define REG_AWB_DAYLIGHT 0x04 253 + #define REG_AWB_CLOUDY 0x05 254 + #define REG_AWB_SHADE 0x06 255 + #define REG_AWB_HORIZON 0x07 256 + #define REG_AWB_LEDLIGHT 0x09 257 + 258 + /* 259 + * Category 7 - EXIF information 260 + */ 261 + #define CAT7_INFO_EXPTIME_NU 0x00 262 + #define CAT7_INFO_EXPTIME_DE 0x04 263 + #define CAT7_INFO_TV_NU 0x08 264 + #define CAT7_INFO_TV_DE 0x0c 265 + #define CAT7_INFO_AV_NU 0x10 266 + #define CAT7_INFO_AV_DE 0x14 267 + #define CAT7_INFO_BV_NU 0x18 268 + #define CAT7_INFO_BV_DE 0x1c 269 + #define CAT7_INFO_EBV_NU 0x20 270 + #define CAT7_INFO_EBV_DE 0x24 271 + #define CAT7_INFO_ISO 0x28 272 + #define CAT7_INFO_FLASH 0x2a 273 + #define CAT7_INFO_SDR 0x2c 274 + #define CAT7_INFO_QVAL 0x2e 275 + 276 + #define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4) 277 + #define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4) 278 + #define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4) 279 + #define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4) 280 + #define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4) 281 + #define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4) 282 + #define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4) 283 + #define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4) 284 + #define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4) 285 + #define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4) 286 + #define EXIF_INFO_ISO I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2) 287 + #define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2) 288 + #define EXIF_INFO_SDR I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2) 289 + #define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2) 290 + 291 + /* 292 + * Category 9 - Face Detection 293 + */ 294 + #define CAT9_FD_CTL 0x00 295 + 296 + #define FD_CTL I2C_REG(CAT_FD, CAT9_FD_CTL, 1) 297 + #define BIT_FD_EN 0 298 + #define BIT_FD_DRAW_FACE_FRAME 4 299 + #define BIT_FD_DRAW_SMILE_LVL 6 300 + #define REG_FD(shift) (1 << shift) 301 + #define REG_FD_OFF 0x0 302 + 303 + /* 304 + * Category A - Lens Parameter 305 + */ 306 + #define CATA_AF_MODE 0x01 307 + #define CATA_AF_EXECUTE 0x02 308 + #define CATA_AF_STATUS 0x03 309 + #define CATA_AF_VERSION 0x0a 310 + 311 + #define AF_MODE I2C_REG(CAT_LENS, CATA_AF_MODE, 1) 312 + #define REG_AF_NORMAL 0x00 /* Normal AF, one time */ 313 + #define REG_AF_MACRO 0x01 /* Macro AF, one time */ 314 + #define REG_AF_POWEROFF 0x07 315 + 316 + #define AF_EXECUTE I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1) 317 + #define REG_AF_STOP 0x00 318 + #define REG_AF_EXE_AUTO 0x01 319 + #define REG_AF_EXE_CAF 0x02 320 + 321 + #define AF_STATUS I2C_REG(CAT_LENS, CATA_AF_STATUS, 1) 322 + #define REG_AF_FAIL 0x00 323 + #define REG_AF_SUCCESS 0x02 324 + #define REG_AF_IDLE 0x04 325 + #define REG_AF_BUSY 0x05 326 + 327 + #define AF_VERSION I2C_REG(CAT_LENS, CATA_AF_VERSION, 1) 328 + 329 + /* 330 + * Category B - CAPTURE Parameter 331 + */ 332 + #define CATB_YUVOUT_MAIN 0x00 333 + #define CATB_MAIN_IMAGE_SIZE 0x01 334 + #define CATB_MCC_MODE 0x1d 335 + #define CATB_WDR_EN 0x2c 336 + #define CATB_LIGHT_CTRL 0x40 337 + #define CATB_FLASH_CTRL 0x41 338 + 339 + #define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1) 340 + #define REG_YUV422 0x00 341 + #define REG_BAYER10 0x05 342 + #define REG_BAYER8 0x06 343 + #define REG_JPEG 0x10 344 + 345 + #define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1) 346 + 347 + #define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1) 348 + #define REG_MCC_OFF 0x00 349 + #define REG_MCC_NORMAL 0x01 350 + 351 + #define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1) 352 + #define REG_WDR_OFF 0x00 353 + #define REG_WDR_ON 0x01 354 + #define REG_WDR_AUTO 0x02 355 + 356 + #define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1) 357 + #define REG_LIGHT_OFF 0x00 358 + #define REG_LIGHT_ON 0x01 359 + #define REG_LIGHT_AUTO 0x02 360 + 361 + #define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1) 362 + #define REG_FLASH_OFF 0x00 363 + #define REG_FLASH_ON 0x01 364 + #define REG_FLASH_AUTO 0x02 365 + 366 + /* 367 + * Category C - CAPTURE Control 368 + */ 369 + #define CATC_CAP_MODE 0x00 370 + #define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi */ 371 + #define CATC_CAP_START 0x09 372 + #define CATC_CAP_IMAGE_SIZE 0x0d 373 + #define CATC_CAP_THUMB_SIZE 0x11 374 + 375 + #define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1) 376 + #define REG_CAP_NONE 0x00 377 + #define REG_CAP_ANTI_SHAKE 0x02 378 + 379 + #define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1) 380 + 381 + #define CAPC_START I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1) 382 + #define REG_CAP_START_MAIN 0x01 383 + #define REG_CAP_START_THUMB 0x03 384 + 385 + #define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 1) 386 + #define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 1) 387 + 388 + /* 389 + * Category F - Flash 390 + * 391 + * This mode provides functions about internal flash stuff and system startup. 392 + */ 393 + #define CATF_CAM_START 0x12 /* It starts internal ARM core booting 394 + * after power-up */ 395 + 396 + #define FLASH_CAM_START I2C_REG(CAT_FLASH, CATF_CAM_START, 1) 397 + #define REG_START_ARM_BOOT 0x01 398 + 399 + #endif /* M5MOLS_REG_H */
+3
drivers/media/video/uvc/Makefile
··· 1 1 uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ 2 2 uvc_status.o uvc_isight.o 3 + ifeq ($(CONFIG_MEDIA_CONTROLLER),y) 4 + uvcvideo-objs += uvc_entity.o 5 + endif 3 6 obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o
+59 -7
drivers/media/video/uvc/uvc_driver.c
··· 248 248 * Terminal and unit management 249 249 */ 250 250 251 - static struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) 251 + struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) 252 252 { 253 253 struct uvc_entity *entity; 254 254 ··· 795 795 struct uvc_entity *entity; 796 796 unsigned int num_inputs; 797 797 unsigned int size; 798 + unsigned int i; 798 799 800 + extra_size = ALIGN(extra_size, sizeof(*entity->pads)); 799 801 num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; 800 - size = sizeof(*entity) + extra_size + num_inputs; 802 + size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads 803 + + num_inputs; 801 804 entity = kzalloc(size, GFP_KERNEL); 802 805 if (entity == NULL) 803 806 return NULL; ··· 808 805 entity->id = id; 809 806 entity->type = type; 810 807 808 + entity->num_links = 0; 809 + entity->num_pads = num_pads; 810 + entity->pads = ((void *)(entity + 1)) + extra_size; 811 + 812 + for (i = 0; i < num_inputs; ++i) 813 + entity->pads[i].flags = MEDIA_PAD_FL_SINK; 814 + if (!UVC_ENTITY_IS_OTERM(entity)) 815 + entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE; 816 + 811 817 entity->bNrInPins = num_inputs; 812 - entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size; 818 + entity->baSourceID = (__u8 *)(&entity->pads[num_pads]); 813 819 814 820 return entity; 815 821 } ··· 1597 1585 uvc_status_cleanup(dev); 1598 1586 uvc_ctrl_cleanup_device(dev); 1599 1587 1588 + if (dev->vdev.dev) 1589 + v4l2_device_unregister(&dev->vdev); 1590 + #ifdef CONFIG_MEDIA_CONTROLLER 1591 + if (media_devnode_is_registered(&dev->mdev.devnode)) 1592 + media_device_unregister(&dev->mdev); 1593 + #endif 1594 + 1600 1595 list_for_each_safe(p, n, &dev->chains) { 1601 1596 struct uvc_video_chain *chain; 1602 1597 chain = list_entry(p, struct uvc_video_chain, list); ··· 1613 1594 list_for_each_safe(p, n, &dev->entities) { 1614 1595 struct uvc_entity *entity; 1615 1596 entity = list_entry(p, struct uvc_entity, list); 1597 + #ifdef CONFIG_MEDIA_CONTROLLER 1598 + uvc_mc_cleanup_entity(entity); 1599 + #endif 1600 + if (entity->vdev) { 1601 + video_device_release(entity->vdev); 1602 + entity->vdev = NULL; 1603 + } 1616 1604 kfree(entity); 1617 1605 } 1618 1606 ··· 1641 1615 { 1642 1616 struct uvc_streaming *stream = video_get_drvdata(vdev); 1643 1617 struct uvc_device *dev = stream->dev; 1644 - 1645 - video_device_release(vdev); 1646 1618 1647 1619 /* Decrement the registered streams count and delete the device when it 1648 1620 * reaches zero. ··· 1706 1682 * unregistered before the reference is released, so we don't need to 1707 1683 * get another one. 1708 1684 */ 1709 - vdev->parent = &dev->intf->dev; 1685 + vdev->v4l2_dev = &dev->vdev; 1710 1686 vdev->fops = &uvc_fops; 1711 1687 vdev->release = uvc_release; 1712 1688 strlcpy(vdev->name, dev->name, sizeof vdev->name); ··· 1755 1731 ret = uvc_register_video(dev, stream); 1756 1732 if (ret < 0) 1757 1733 return ret; 1734 + 1735 + term->vdev = stream->vdev; 1758 1736 } 1759 1737 1760 1738 return 0; ··· 1771 1745 ret = uvc_register_terms(dev, chain); 1772 1746 if (ret < 0) 1773 1747 return ret; 1748 + 1749 + #ifdef CONFIG_MEDIA_CONTROLLER 1750 + ret = uvc_mc_register_entities(chain); 1751 + if (ret < 0) { 1752 + uvc_printk(KERN_INFO, "Failed to register entites " 1753 + "(%d).\n", ret); 1754 + } 1755 + #endif 1774 1756 } 1775 1757 1776 1758 return 0; ··· 1848 1814 "linux-uvc-devel mailing list.\n"); 1849 1815 } 1850 1816 1817 + /* Register the media and V4L2 devices. */ 1818 + #ifdef CONFIG_MEDIA_CONTROLLER 1819 + dev->mdev.dev = &intf->dev; 1820 + strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); 1821 + if (udev->serial) 1822 + strlcpy(dev->mdev.serial, udev->serial, 1823 + sizeof(dev->mdev.serial)); 1824 + strcpy(dev->mdev.bus_info, udev->devpath); 1825 + dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); 1826 + dev->mdev.driver_version = DRIVER_VERSION_NUMBER; 1827 + if (media_device_register(&dev->mdev) < 0) 1828 + goto error; 1829 + 1830 + dev->vdev.mdev = &dev->mdev; 1831 + #endif 1832 + if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) 1833 + goto error; 1834 + 1851 1835 /* Initialize controls. */ 1852 1836 if (uvc_ctrl_init_device(dev) < 0) 1853 1837 goto error; ··· 1874 1822 if (uvc_scan_device(dev) < 0) 1875 1823 goto error; 1876 1824 1877 - /* Register video devices. */ 1825 + /* Register video device nodes. */ 1878 1826 if (uvc_register_chains(dev) < 0) 1879 1827 goto error; 1880 1828
+118
drivers/media/video/uvc/uvc_entity.c
··· 1 + /* 2 + * uvc_entity.c -- USB Video Class driver 3 + * 4 + * Copyright (C) 2005-2011 5 + * Laurent Pinchart (laurent.pinchart@ideasonboard.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 as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + * 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/list.h> 16 + #include <linux/videodev2.h> 17 + 18 + #include <media/v4l2-common.h> 19 + 20 + #include "uvcvideo.h" 21 + 22 + /* ------------------------------------------------------------------------ 23 + * Video subdevices registration and unregistration 24 + */ 25 + 26 + static int uvc_mc_register_entity(struct uvc_video_chain *chain, 27 + struct uvc_entity *entity) 28 + { 29 + const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; 30 + struct uvc_entity *remote; 31 + unsigned int i; 32 + u8 remote_pad; 33 + int ret; 34 + 35 + for (i = 0; i < entity->num_pads; ++i) { 36 + struct media_entity *source; 37 + struct media_entity *sink; 38 + 39 + if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) 40 + continue; 41 + 42 + remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]); 43 + if (remote == NULL) 44 + return -EINVAL; 45 + 46 + source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) 47 + ? &remote->vdev->entity : &remote->subdev.entity; 48 + sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) 49 + ? &entity->vdev->entity : &entity->subdev.entity; 50 + 51 + remote_pad = remote->num_pads - 1; 52 + ret = media_entity_create_link(source, remote_pad, 53 + sink, i, flags); 54 + if (ret < 0) 55 + return ret; 56 + } 57 + 58 + if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) 59 + ret = v4l2_device_register_subdev(&chain->dev->vdev, 60 + &entity->subdev); 61 + 62 + return ret; 63 + } 64 + 65 + static struct v4l2_subdev_ops uvc_subdev_ops = { 66 + }; 67 + 68 + void uvc_mc_cleanup_entity(struct uvc_entity *entity) 69 + { 70 + if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) 71 + media_entity_cleanup(&entity->subdev.entity); 72 + else if (entity->vdev != NULL) 73 + media_entity_cleanup(&entity->vdev->entity); 74 + } 75 + 76 + static int uvc_mc_init_entity(struct uvc_entity *entity) 77 + { 78 + int ret; 79 + 80 + if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) { 81 + v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); 82 + strlcpy(entity->subdev.name, entity->name, 83 + sizeof(entity->subdev.name)); 84 + 85 + ret = media_entity_init(&entity->subdev.entity, 86 + entity->num_pads, entity->pads, 0); 87 + } else 88 + ret = media_entity_init(&entity->vdev->entity, 89 + entity->num_pads, entity->pads, 0); 90 + 91 + return ret; 92 + } 93 + 94 + int uvc_mc_register_entities(struct uvc_video_chain *chain) 95 + { 96 + struct uvc_entity *entity; 97 + int ret; 98 + 99 + list_for_each_entry(entity, &chain->entities, chain) { 100 + ret = uvc_mc_init_entity(entity); 101 + if (ret < 0) { 102 + uvc_printk(KERN_INFO, "Failed to initialize entity for " 103 + "entity %u\n", entity->id); 104 + return ret; 105 + } 106 + } 107 + 108 + list_for_each_entry(entity, &chain->entities, chain) { 109 + ret = uvc_mc_register_entity(chain, entity); 110 + if (ret < 0) { 111 + uvc_printk(KERN_INFO, "Failed to register entity for " 112 + "entity %u\n", entity->id); 113 + return ret; 114 + } 115 + } 116 + 117 + return 0; 118 + }
+20
drivers/media/video/uvc/uvcvideo.h
··· 98 98 #ifdef __KERNEL__ 99 99 100 100 #include <linux/poll.h> 101 + #include <linux/usb.h> 101 102 #include <linux/usb/video.h> 102 103 #include <linux/uvcvideo.h> 104 + #include <media/media-device.h> 105 + #include <media/v4l2-device.h> 103 106 104 107 /* -------------------------------------------------------------------------- 105 108 * UVC constants ··· 303 300 __u8 id; 304 301 __u16 type; 305 302 char name[64]; 303 + 304 + /* Media controller-related fields. */ 305 + struct video_device *vdev; 306 + struct v4l2_subdev subdev; 307 + unsigned int num_pads; 308 + unsigned int num_links; 309 + struct media_pad *pads; 306 310 307 311 union { 308 312 struct { ··· 514 504 atomic_t nmappings; 515 505 516 506 /* Video control interface */ 507 + #ifdef CONFIG_MEDIA_CONTROLLER 508 + struct media_device mdev; 509 + #endif 510 + struct v4l2_device vdev; 517 511 __u16 uvc_version; 518 512 __u32 clock_frequency; 519 513 ··· 597 583 /* Core driver */ 598 584 extern struct uvc_driver uvc_driver; 599 585 586 + extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id); 587 + 600 588 /* Video buffers queue management. */ 601 589 extern void uvc_queue_init(struct uvc_video_queue *queue, 602 590 enum v4l2_buf_type type, int drop_corrupted); ··· 631 615 632 616 /* V4L2 interface */ 633 617 extern const struct v4l2_file_operations uvc_fops; 618 + 619 + /* Media controller */ 620 + extern int uvc_mc_register_entities(struct uvc_video_chain *chain); 621 + extern void uvc_mc_cleanup_entity(struct uvc_entity *entity); 634 622 635 623 /* Video */ 636 624 extern int uvc_video_init(struct uvc_streaming *stream);
+35
include/media/m5mols.h
··· 1 + /* 2 + * Driver header for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #ifndef MEDIA_M5MOLS_H 17 + #define MEDIA_M5MOLS_H 18 + 19 + /** 20 + * struct m5mols_platform_data - platform data for M-5MOLS driver 21 + * @irq: GPIO getting the irq pin of M-5MOLS 22 + * @gpio_reset: GPIO driving the reset pin of M-5MOLS 23 + * @reset_polarity: active state for gpio_rst pin, 0 or 1 24 + * @set_power: an additional callback to the board setup code 25 + * to be called after enabling and before disabling 26 + * the sensor's supply regulators 27 + */ 28 + struct m5mols_platform_data { 29 + int irq; 30 + int gpio_reset; 31 + u8 reset_polarity; 32 + int (*set_power)(struct device *dev, int on); 33 + }; 34 + 35 + #endif /* MEDIA_M5MOLS_H */
+4
include/media/videobuf-dvb.h
··· 4 4 #include <dvb_net.h> 5 5 #include <dvb_frontend.h> 6 6 7 + #ifndef _VIDEOBUF_DVB_H_ 8 + #define _VIDEOBUF_DVB_H_ 9 + 7 10 struct videobuf_dvb { 8 11 /* filling that the job of the driver */ 9 12 char *name; ··· 57 54 struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id); 58 55 int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p); 59 56 57 + #endif /* _VIDEOBUF_DVB_H_ */ 60 58 61 59 /* 62 60 * Local variables: