Commit c0880dcd authored by Linus Torvalds's avatar Linus Torvalds

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
parents f7fc06e3 616a4b83
...@@ -141,13 +141,15 @@ struct dtv_properties { ...@@ -141,13 +141,15 @@ struct dtv_properties {
</row></tbody></tgroup></informaltable> </row></tbody></tgroup></informaltable>
</section> </section>
<section>
<title>Property types</title>
<para> <para>
On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>, On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to
get/set up to 64 properties. The actual meaning of each property is described on the next sections. get/set up to 64 properties. The actual meaning of each property is described on the next sections.
</para> </para>
<para>The Available frontend property types are:</para> <para>The available frontend property types are:</para>
<programlisting> <programlisting>
#define DTV_UNDEFINED 0 #define DTV_UNDEFINED 0
#define DTV_TUNE 1 #define DTV_TUNE 1
...@@ -193,6 +195,7 @@ get/set up to 64 properties. The actual meaning of each property is described on ...@@ -193,6 +195,7 @@ get/set up to 64 properties. The actual meaning of each property is described on
#define DTV_ISDBT_LAYER_ENABLED 41 #define DTV_ISDBT_LAYER_ENABLED 41
#define DTV_ISDBS_TS_ID 42 #define DTV_ISDBS_TS_ID 42
</programlisting> </programlisting>
</section>
<section id="fe_property_common"> <section id="fe_property_common">
<title>Parameters that are common to all Digital TV standards</title> <title>Parameters that are common to all Digital TV standards</title>
......
...@@ -293,6 +293,7 @@ ...@@ -293,6 +293,7 @@
<!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml"> <!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
<!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml"> <!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
<!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml"> <!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
<!ENTITY sub-srggb12 SYSTEM "v4l/pixfmt-srggb12.xml">
<!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml"> <!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
<!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml"> <!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
<!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml"> <!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
...@@ -373,9 +374,9 @@ ...@@ -373,9 +374,9 @@
<!ENTITY sub-media-indices SYSTEM "media-indices.tmpl"> <!ENTITY sub-media-indices SYSTEM "media-indices.tmpl">
<!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml"> <!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml">
<!ENTITY sub-media-open SYSTEM "v4l/media-func-open.xml"> <!ENTITY sub-media-func-open SYSTEM "v4l/media-func-open.xml">
<!ENTITY sub-media-close SYSTEM "v4l/media-func-close.xml"> <!ENTITY sub-media-func-close SYSTEM "v4l/media-func-close.xml">
<!ENTITY sub-media-ioctl SYSTEM "v4l/media-func-ioctl.xml"> <!ENTITY sub-media-func-ioctl SYSTEM "v4l/media-func-ioctl.xml">
<!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml"> <!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml">
<!ENTITY sub-media-ioc-enum-entities SYSTEM "v4l/media-ioc-enum-entities.xml"> <!ENTITY sub-media-ioc-enum-entities SYSTEM "v4l/media-ioc-enum-entities.xml">
<!ENTITY sub-media-ioc-enum-links SYSTEM "v4l/media-ioc-enum-links.xml"> <!ENTITY sub-media-ioc-enum-links SYSTEM "v4l/media-ioc-enum-links.xml">
......
...@@ -78,9 +78,9 @@ ...@@ -78,9 +78,9 @@
<appendix id="media-user-func"> <appendix id="media-user-func">
<title>Function Reference</title> <title>Function Reference</title>
<!-- Keep this alphabetically sorted. --> <!-- Keep this alphabetically sorted. -->
&sub-media-open; &sub-media-func-open;
&sub-media-close; &sub-media-func-close;
&sub-media-ioctl; &sub-media-func-ioctl;
<!-- All ioctls go here. --> <!-- All ioctls go here. -->
&sub-media-ioc-device-info; &sub-media-ioc-device-info;
&sub-media-ioc-enum-entities; &sub-media-ioc-enum-entities;
......
...@@ -673,6 +673,7 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.< ...@@ -673,6 +673,7 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.<
&sub-srggb8; &sub-srggb8;
&sub-sbggr16; &sub-sbggr16;
&sub-srggb10; &sub-srggb10;
&sub-srggb12;
</section> </section>
<section id="yuv-formats"> <section id="yuv-formats">
......
...@@ -2531,13 +2531,13 @@ ...@@ -2531,13 +2531,13 @@
<constant>_JPEG</constant> prefix the format code is made of <constant>_JPEG</constant> prefix the format code is made of
the following information. the following information.
<itemizedlist> <itemizedlist>
<listitem>The number of bus samples per entropy encoded byte.</listitem> <listitem><para>The number of bus samples per entropy encoded byte.</para></listitem>
<listitem>The bus width.</listitem> <listitem><para>The bus width.</para></listitem>
</itemizedlist> </itemizedlist>
</para>
<para>For instance, for a JPEG baseline process and an 8-bit bus width <para>For instance, for a JPEG baseline process and an 8-bit bus width
the format will be named <constant>V4L2_MBUS_FMT_JPEG_1X8</constant>. the format will be named <constant>V4L2_MBUS_FMT_JPEG_1X8</constant>.
</para>
</para> </para>
<para>The following table lists existing JPEG compressed formats.</para> <para>The following table lists existing JPEG compressed formats.</para>
......
This diff is collapsed.
...@@ -207,17 +207,6 @@ static int lme2510_stream_restart(struct dvb_usb_device *d) ...@@ -207,17 +207,6 @@ static int lme2510_stream_restart(struct dvb_usb_device *d)
rbuff, sizeof(rbuff)); rbuff, sizeof(rbuff));
return ret; return ret;
} }
static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress)
{
struct dvb_usb_device *d = adap->dev;
deb_info(1, "INT Key Keypress =%04x", keypress);
if (keypress > 0)
rc_keydown(d->rc_dev, keypress, 0);
return 0;
}
static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out)
{ {
...@@ -256,6 +245,7 @@ static void lme2510_int_response(struct urb *lme_urb) ...@@ -256,6 +245,7 @@ static void lme2510_int_response(struct urb *lme_urb)
struct lme2510_state *st = adap->dev->priv; struct lme2510_state *st = adap->dev->priv;
static u8 *ibuf, *rbuf; static u8 *ibuf, *rbuf;
int i = 0, offset; int i = 0, offset;
u32 key;
switch (lme_urb->status) { switch (lme_urb->status) {
case 0: case 0:
...@@ -282,10 +272,16 @@ static void lme2510_int_response(struct urb *lme_urb) ...@@ -282,10 +272,16 @@ static void lme2510_int_response(struct urb *lme_urb)
switch (ibuf[0]) { switch (ibuf[0]) {
case 0xaa: case 0xaa:
debug_data_snipet(1, "INT Remote data snipet in", ibuf); debug_data_snipet(1, "INT Remote data snipet", ibuf);
lme2510_remote_keypress(adap, if ((ibuf[4] + ibuf[5]) == 0xff) {
(u32)(ibuf[2] << 24) + (ibuf[3] << 16) + key = ibuf[5];
(ibuf[4] << 8) + ibuf[5]); key += (ibuf[3] > 0)
? (ibuf[3] ^ 0xff) << 8 : 0;
key += (ibuf[2] ^ 0xff) << 16;
deb_info(1, "INT Key =%08x", key);
if (adap->dev->rc_dev != NULL)
rc_keydown(adap->dev->rc_dev, key, 0);
}
break; break;
case 0xbb: case 0xbb:
switch (st->tuner_config) { switch (st->tuner_config) {
...@@ -691,45 +687,6 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) ...@@ -691,45 +687,6 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
return (ret < 0) ? -ENODEV : 0; return (ret < 0) ? -ENODEV : 0;
} }
static int lme2510_int_service(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
struct rc_dev *rc;
int ret;
info("STA Configuring Remote");
rc = rc_allocate_device();
if (!rc)
return -ENOMEM;
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
rc->input_name = "LME2510 Remote Control";
rc->input_phys = d->rc_phys;
rc->map_name = RC_MAP_LME2510;
rc->driver_name = "LME 2510";
usb_to_input_id(d->udev, &rc->input_id);
ret = rc_register_device(rc);
if (ret) {
rc_free_device(rc);
return ret;
}
d->rc_dev = rc;
/* Start the Interrupt */
ret = lme2510_int_read(adap);
if (ret < 0) {
rc_unregister_device(rc);
info("INT Unable to start Interrupt Service");
return -ENODEV;
}
return 0;
}
static u8 check_sum(u8 *p, u8 len) static u8 check_sum(u8 *p, u8 len)
{ {
u8 sum = 0; u8 sum = 0;
...@@ -831,7 +788,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) ...@@ -831,7 +788,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
cold_fw = !cold; cold_fw = !cold;
if (udev->descriptor.idProduct == 0x1122) { if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) {
switch (dvb_usb_lme2510_firmware) { switch (dvb_usb_lme2510_firmware) {
default: default:
dvb_usb_lme2510_firmware = TUNER_S0194; dvb_usb_lme2510_firmware = TUNER_S0194;
...@@ -1053,8 +1010,11 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) ...@@ -1053,8 +1010,11 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
end: if (ret) { end: if (ret) {
kfree(adap->fe); if (adap->fe) {
adap->fe = NULL; dvb_frontend_detach(adap->fe);
adap->fe = NULL;
}
adap->dev->props.rc.core.rc_codes = NULL;
return -ENODEV; return -ENODEV;
} }
...@@ -1097,8 +1057,12 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) ...@@ -1097,8 +1057,12 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
return -ENODEV; return -ENODEV;
} }
/* Start the Interrupt & Remote*/ /* Start the Interrupt*/
ret = lme2510_int_service(adap); ret = lme2510_int_read(adap);
if (ret < 0) {
info("INT Unable to start Interrupt Service");
return -ENODEV;
}
return ret; return ret;
} }
...@@ -1204,6 +1168,12 @@ static struct dvb_usb_device_properties lme2510_properties = { ...@@ -1204,6 +1168,12 @@ static struct dvb_usb_device_properties lme2510_properties = {
} }
} }
}, },
.rc.core = {
.protocol = RC_TYPE_NEC,
.module_name = "LME2510 Remote Control",
.allowed_protos = RC_TYPE_NEC,
.rc_codes = RC_MAP_LME2510,
},
.power_ctrl = lme2510_powerup, .power_ctrl = lme2510_powerup,
.identify_state = lme2510_identify_state, .identify_state = lme2510_identify_state,
.i2c_algo = &lme2510_i2c_algo, .i2c_algo = &lme2510_i2c_algo,
...@@ -1246,6 +1216,12 @@ static struct dvb_usb_device_properties lme2510c_properties = { ...@@ -1246,6 +1216,12 @@ static struct dvb_usb_device_properties lme2510c_properties = {
} }
} }
}, },
.rc.core = {
.protocol = RC_TYPE_NEC,
.module_name = "LME2510 Remote Control",
.allowed_protos = RC_TYPE_NEC,
.rc_codes = RC_MAP_LME2510,
},
.power_ctrl = lme2510_powerup, .power_ctrl = lme2510_powerup,
.identify_state = lme2510_identify_state, .identify_state = lme2510_identify_state,
.i2c_algo = &lme2510_i2c_algo, .i2c_algo = &lme2510_i2c_algo,
...@@ -1269,19 +1245,21 @@ static void *lme2510_exit_int(struct dvb_usb_device *d) ...@@ -1269,19 +1245,21 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
adap->feedcount = 0; adap->feedcount = 0;
} }
if (st->lme_urb != NULL) { if (st->usb_buffer != NULL) {
st->i2c_talk_onoff = 1; st->i2c_talk_onoff = 1;
st->signal_lock = 0; st->signal_lock = 0;
st->signal_level = 0; st->signal_level = 0;
st->signal_sn = 0; st->signal_sn = 0;
buffer = st->usb_buffer; buffer = st->usb_buffer;
}
if (st->lme_urb != NULL) {
usb_kill_urb(st->lme_urb); usb_kill_urb(st->lme_urb);
usb_free_coherent(d->udev, 5000, st->buffer, usb_free_coherent(d->udev, 5000, st->buffer,
st->lme_urb->transfer_dma); st->lme_urb->transfer_dma);
info("Interrupt Service Stopped"); info("Interrupt Service Stopped");
rc_unregister_device(d->rc_dev);
info("Remote Stopped");
} }
return buffer; return buffer;
} }
...@@ -1293,7 +1271,8 @@ static void lme2510_exit(struct usb_interface *intf) ...@@ -1293,7 +1271,8 @@ static void lme2510_exit(struct usb_interface *intf)
if (d != NULL) { if (d != NULL) {
usb_buffer = lme2510_exit_int(d); usb_buffer = lme2510_exit_int(d);
dvb_usb_device_exit(intf); dvb_usb_device_exit(intf);
kfree(usb_buffer); if (usb_buffer != NULL)
kfree(usb_buffer);
} }
} }
...@@ -1327,5 +1306,5 @@ module_exit(lme2510_module_exit); ...@@ -1327,5 +1306,5 @@ module_exit(lme2510_module_exit);
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
MODULE_VERSION("1.86"); MODULE_VERSION("1.88");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "stb0899_priv.h" #include "stb0899_priv.h"
#include "stb0899_reg.h" #include "stb0899_reg.h"
inline u32 stb0899_do_div(u64 n, u32 d) static inline u32 stb0899_do_div(u64 n, u32 d)
{ {
/* wrap do_div() for ease of use */ /* wrap do_div() for ease of use */
......
...@@ -224,7 +224,6 @@ struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe, ...@@ -224,7 +224,6 @@ struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
} }
EXPORT_SYMBOL(tda8261_attach); EXPORT_SYMBOL(tda8261_attach);
MODULE_PARM_DESC(verbose, "Set verbosity level");
MODULE_AUTHOR("Manu Abraham"); MODULE_AUTHOR("Manu Abraham");
MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner"); MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
......
...@@ -1382,7 +1382,7 @@ static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl) ...@@ -1382,7 +1382,7 @@ static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_TUNE_ANTENNA_CAPACITOR: case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
ctrl->val = wl1273_fm_get_tx_ctune(radio); ctrl->cur.val = wl1273_fm_get_tx_ctune(radio);
break; break;
default: default:
......
...@@ -191,7 +191,7 @@ static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl) ...@@ -191,7 +191,7 @@ static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_TUNE_ANTENNA_CAPACITOR: case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
ctrl->val = fm_tx_get_tune_cap_val(fmdev); ctrl->cur.val = fm_tx_get_tune_cap_val(fmdev);
break; break;
default: default:
fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id); fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id);
......
...@@ -148,6 +148,18 @@ config IR_ITE_CIR ...@@ -148,6 +148,18 @@ config IR_ITE_CIR
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ite-cir. module will be called ite-cir.
config IR_FINTEK
tristate "Fintek Consumer Infrared Transceiver"
depends on PNP
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receiver
/transciever made by Fintek. This chip is found on assorted
Jetway motherboards (and of course, possibly others).
To compile this driver as a module, choose M here: the
module will be called fintek-cir.
config IR_NUVOTON config IR_NUVOTON
tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
depends on PNP depends on PNP
......
...@@ -16,6 +16,7 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o ...@@ -16,6 +16,7 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
obj-$(CONFIG_IR_IMON) += imon.o obj-$(CONFIG_IR_IMON) += imon.o
obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
obj-$(CONFIG_IR_MCEUSB) += mceusb.o obj-$(CONFIG_IR_MCEUSB) += mceusb.o
obj-$(CONFIG_IR_FINTEK) += fintek-cir.o
obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
obj-$(CONFIG_IR_ENE) += ene_ir.o obj-$(CONFIG_IR_ENE) += ene_ir.o
obj-$(CONFIG_IR_REDRAT3) += redrat3.o obj-$(CONFIG_IR_REDRAT3) += redrat3.o
......
This diff is collapsed.
/*
* Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR
*
* Copyright (C) 2011 Jarod Wilson <jarod@redhat.com>
*
* Special thanks to Fintek for providing hardware and spec sheets.
* This driver is based upon the nuvoton, ite and ene drivers for
* similar hardware.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <linux/spinlock.h>
#include <linux/ioctl.h>
/* platform driver name to register */
#define FINTEK_DRIVER_NAME "fintek-cir"
#define FINTEK_DESCRIPTION "Fintek LPC SuperIO Consumer IR Transceiver"
#define VENDOR_ID_FINTEK 0x1934
/* debugging module parameter */
static int debug;
#define fit_pr(level, text, ...) \
printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
#define fit_dbg(text, ...) \
if (debug) \
printk(KERN_DEBUG \
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
#define fit_dbg_verbose(text, ...) \
if (debug > 1) \
printk(KERN_DEBUG \
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
#define fit_dbg_wake(text, ...) \
if (debug > 2) \
printk(KERN_DEBUG \
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
#define TX_BUF_LEN 256
#define RX_BUF_LEN 32
struct fintek_dev {
struct pnp_dev *pdev;
struct rc_dev *rdev;
spinlock_t fintek_lock;
/* for rx */
u8 buf[RX_BUF_LEN];
unsigned int pkts;
struct {
spinlock_t lock;
u8 buf[TX_BUF_LEN];
unsigned int buf_count;
unsigned int cur_buf_num;
wait_queue_head_t queue;
} tx;
/* Config register index/data port pair */
u8 cr_ip;
u8 cr_dp;
/* hardware I/O settings */
unsigned long cir_addr;
int cir_irq;
int cir_port_len;
/* hardware id */
u8 chip_major;
u8 chip_minor;
u16 chip_vendor;
/* hardware features */
bool hw_learning_capable;
bool hw_tx_capable;
/* rx settings */
bool learning_enabled;
bool carrier_detect_enabled;
enum {
CMD_HEADER = 0,
SUBCMD,
CMD_DATA,
PARSE_IRDATA,
} parser_state;
u8 cmd, rem;
/* carrier period = 1 / frequency */
u32 carrier;
};
/* buffer packet constants, largely identical to mceusb.c */
#define BUF_PULSE_BIT 0x80
#define BUF_LEN_MASK 0x1f
#define BUF_SAMPLE_MASK 0x7f
#define BUF_COMMAND_HEADER 0x9f
#define BUF_COMMAND_MASK 0xe0
#define BUF_COMMAND_NULL 0x00
#define BUF_HW_CMD_HEADER 0xff
#define BUF_CMD_G_REVISION 0x0b
#define BUF_CMD_S_CARRIER 0x06
#define BUF_CMD_S_TIMEOUT 0x0c
#define BUF_CMD_SIG_END 0x01
#define BUF_CMD_S_TXMASK 0x08
#define BUF_CMD_S_RXSENSOR 0x14
#define BUF_RSP_PULSE_COUNT 0x15
#define CIR_SAMPLE_PERIOD 50
/*
* Configuration Register:
* Index Port
* Data Port
*/
#define CR_INDEX_PORT 0x2e
#define CR_DATA_PORT 0x2f
/* Possible alternate values, depends on how the chip is wired */
#define CR_INDEX_PORT2 0x4e
#define CR_DATA_PORT2 0x4f
/*
* GCR_CONFIG_PORT_SEL bit 4 specifies which Index Port value is
* active. 1 = 0x4e, 0 = 0x2e
*/
#define PORT_SEL_PORT_4E_EN 0x10
/* Extended Function Mode enable/disable magic values */
#define CONFIG_REG_ENABLE 0x87
#define CONFIG_REG_DISABLE 0xaa
/* Chip IDs found in CR_CHIP_ID_{HI,LO} */
#define CHIP_ID_HIGH_F71809U 0x04
#define CHIP_ID_LOW_F71809U 0x08
/*
* Global control regs we need to care about:
* Global Control def.
* Register name addr val. */
#define GCR_SOFTWARE_RESET 0x02 /* 0x00 */
#define GCR_LOGICAL_DEV_NO 0x07 /* 0x00 */
#define GCR_CHIP_ID_HI 0x20 /* 0x04 */
#define GCR_CHIP_ID_LO 0x21 /* 0x08 */
#define GCR_VENDOR_ID_HI 0x23 /* 0x19 */
#define GCR_VENDOR_ID_LO 0x24 /* 0x34 */
#define GCR_CONFIG_PORT_SEL 0x25 /* 0x01 */
#define GCR_KBMOUSE_WAKEUP 0x27
#define LOGICAL_DEV_DISABLE 0x00
#define LOGICAL_DEV_ENABLE 0x01
/* Logical device number of the CIR function */
#define LOGICAL_DEV_CIR 0x05
/* CIR Logical Device (LDN 0x08) config registers */
#define CIR_CR_COMMAND_INDEX 0x04
#define CIR_CR_IRCS 0x05 /* Before host writes command to IR, host
must set to 1. When host finshes write
command to IR, host must clear to 0. */
#define CIR_CR_COMMAND_DATA 0x06 /* Host read or write comand data */
#define CIR_CR_CLASS 0x07 /* 0xff = rx-only, 0x66 = rx + 2 tx,
0x33 = rx + 1 tx */
#define CIR_CR_DEV_EN 0x30 /* bit0 = 1 enables CIR */
#define CIR_CR_BASE_ADDR_HI 0x60 /* MSB of CIR IO base addr */
#define CIR_CR_BASE_ADDR_LO 0x61 /* LSB of CIR IO base addr */
#define CIR_CR_IRQ_SEL 0x70 /* bits3-0 store CIR IRQ */
#define CIR_CR_PSOUT_STATUS 0xf1
#define CIR_CR_WAKE_KEY3_ADDR 0xf8
#define CIR_CR_WAKE_KEY3_CODE 0xf9
#define CIR_CR_WAKE_KEY3_DC 0xfa
#define CIR_CR_WAKE_CONTROL 0xfb
#define CIR_CR_WAKE_KEY12_ADDR 0xfc
#define CIR_CR_WAKE_KEY4_ADDR 0xfd
#define CIR_CR_WAKE_KEY5_ADDR 0xfe
#define CLASS_RX_ONLY 0xff
#define CLASS_RX_2TX 0x66
#define CLASS_RX_1TX 0x33
/* CIR device registers */
#define CIR_STATUS 0x00
#define CIR_RX_DATA 0x01
#define CIR_TX_CONTROL 0x02
#define CIR_TX_DATA 0x03
#define CIR_CONTROL 0x04
/* Bits to enable CIR wake */
#define LOGICAL_DEV_ACPI 0x01
#define LDEV_ACPI_WAKE_EN_REG 0xe8
#define ACPI_WAKE_EN_CIR_BIT 0x04
#define LDEV_ACPI_PME_EN_REG 0xf0
#define LDEV_ACPI_PME_CLR_REG 0xf1
#define ACPI_PME_CIR_BIT 0x02
#define LDEV_ACPI_STATE_REG 0xf4
#define ACPI_STATE_CIR_BIT 0x20
/*
* CIR status register (0x00):
* 7 - CIR_IRQ_EN (1 = enable CIR IRQ, 0 = disable)
* 3 - TX_FINISH (1 when TX finished, write 1 to clear)
* 2 - TX_UNDERRUN (1 on TX underrun, write 1 to clear)
* 1 - RX_TIMEOUT (1 on RX timeout, write 1 to clear)
* 0 - RX_RECEIVE (1 on RX receive, write 1 to clear)
*/
#define CIR_STATUS_IRQ_EN 0x80
#define CIR_STATUS_TX_FINISH 0x08
#define CIR_STATUS_TX_UNDERRUN 0x04
#define CIR_STATUS_RX_TIMEOUT 0x02
#define CIR_STATUS_RX_RECEIVE 0x01
#define CIR_STATUS_IRQ_MASK 0x0f
/*
* CIR TX control register (0x02):
* 7 - TX_START (1 to indicate TX start, auto-cleared when done)
* 6 - TX_END (1 to indicate TX data written to TX fifo)
*/
#define CIR_TX_CONTROL_TX_START 0x80
#define CIR_TX_CONTROL_TX_END 0x40
...@@ -14,81 +14,81 @@ ...@@ -14,81 +14,81 @@
static struct rc_map_table lme2510_rc[] = { static struct rc_map_table lme2510_rc[] = {
/* Type 1 - 26 buttons */ /* Type 1 - 26 buttons */
{ 0xef12ba45, KEY_0 }, { 0x10ed45, KEY_0 },
{ 0xef12a05f, KEY_1 }, { 0x10ed5f, KEY_1 },
{ 0xef12af50, KEY_2 }, { 0x10ed50, KEY_2 },
{ 0xef12a25d, KEY_3 }, { 0x10ed5d, KEY_3 },
{ 0xef12be41, KEY_4 }, { 0x10ed41, KEY_4 },
{ 0xef12f50a, KEY_5 }, { 0x10ed0a, KEY_5 },
{ 0xef12bd42, KEY_6 }, { 0x10ed42, KEY_6 },
{ 0xef12b847, KEY_7 }, { 0x10ed47, KEY_7 },
{ 0xef12b649, KEY_8 }, { 0x10ed49, KEY_8 },
{ 0xef12fa05, KEY_9 }, { 0x10ed05, KEY_9 },
{ 0xef12bc43, KEY_POWER }, { 0x10ed43, KEY_POWER },
{ 0xef12b946, KEY_SUBTITLE }, { 0x10ed46, KEY_SUBTITLE },
{ 0xef12f906, KEY_PAUSE }, { 0x10ed06, KEY_PAUSE },
{ 0xef12fc03, KEY_MEDIA_REPEAT}, { 0x10ed03, KEY_MEDIA_REPEAT},
{ 0xef12fd02, KEY_PAUSE }, { 0x10ed02, KEY_PAUSE },
{ 0xef12a15e, KEY_VOLUMEUP }, { 0x10ed5e, KEY_VOLUMEUP },
{ 0xef12a35c, KEY_VOLUMEDOWN }, { 0x10ed5c, KEY_VOLUMEDOWN },
{ 0xef12f609, KEY_CHANNELUP }, { 0x10ed09, KEY_CHANNELUP },
{ 0xef12e51a, KEY_CHANNELDOWN }, { 0x10ed1a, KEY_CHANNELDOWN },
{ 0xef12e11e, KEY_PLAY }, { 0x10ed1e, KEY_PLAY },
{ 0xef12e41b, KEY_ZOOM }, { 0x10ed1b, KEY_ZOOM },
{ 0xef12a659, KEY_MUTE }, { 0x10ed59, KEY_MUTE },
{ 0xef12a55a, KEY_TV }, { 0x10ed5a, KEY_TV },
{ 0xef12e718, KEY_RECORD }, { 0x10ed18, KEY_RECORD },
{ 0xef12f807, KEY_EPG }, { 0x10ed07, KEY_EPG },
{ 0xef12fe01, KEY_STOP }, { 0x10ed01, KEY_STOP },
/* Type 2 - 20 buttons */ /* Type 2 - 20 buttons */
{ 0xff40ea15, KEY_0 }, { 0xbf15, KEY_0 },
{ 0xff40f708, KEY_1 }, { 0xbf08, KEY_1 },
{ 0xff40f609, KEY_2 }, { 0xbf09, KEY_2 },
{ 0xff40f50a, KEY_3 }, { 0xbf0a, KEY_3 },
{ 0xff40f30c, KEY_4 }, { 0xbf0c, KEY_4 },
{ 0xff40f20d, KEY_5 }, { 0xbf0d, KEY_5 },
{ 0xff40f10e, KEY_6 }, { 0xbf0e, KEY_6 },
{ 0xff40ef10, KEY_7 }, { 0xbf10, KEY_7 },
{ 0xff40ee11, KEY_8 }, { 0xbf11, KEY_8 },
{ 0xff40ed12, KEY_9 }, { 0xbf12, KEY_9 },
{ 0xff40ff00, KEY_POWER }, { 0xbf00, KEY_POWER },
{ 0xff40fb04, KEY_MEDIA_REPEAT}, /* Recall */ { 0xbf04, KEY_MEDIA_REPEAT}, /* Recall */
{ 0xff40e51a, KEY_PAUSE }, /* Timeshift */ { 0xbf1a, KEY_PAUSE }, /* Timeshift */
{ 0xff40fd02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ { 0xbf02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
{ 0xff40f906, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ { 0xbf06, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
{ 0xff40fe01, KEY_CHANNELUP }, { 0xbf01, KEY_CHANNELUP },
{ 0xff40fa05, KEY_CHANNELDOWN }, { 0xbf05, KEY_CHANNELDOWN },
{ 0xff40eb14, KEY_ZOOM }, { 0xbf14, KEY_ZOOM },
{ 0xff40e718, KEY_RECORD }, { 0xbf18, KEY_RECORD },
{ 0xff40e916, KEY_STOP }, { 0xbf16, KEY_STOP },
/* Type 3 - 20 buttons */ /* Type 3 - 20 buttons */
{ 0xff00e31c, KEY_0 }, { 0x1c, KEY_0 },
{ 0xff00f807, KEY_1 }, { 0x07, KEY_1 },
{ 0xff00ea15, KEY_2 }, { 0x15, KEY_2 },
{ 0xff00f609, KEY_3 }, { 0x09, KEY_3 },
{ 0xff00e916, KEY_4 }, { 0x16, KEY_4 },
{ 0xff00e619, KEY_5 }, { 0x19, KEY_5 },
{ 0xff00f20d, KEY_6 }, { 0x0d, KEY_6 },
{ 0xff00f30c, KEY_7 }, { 0x0c, KEY_7 },
{ 0xff00e718, KEY_8 }, { 0x18, KEY_8 },
{ 0xff00a15e, KEY_9 }, { 0x5e, KEY_9 },
{ 0xff00ba45, KEY_POWER }, { 0x45, KEY_POWER },
{ 0xff00bb44, KEY_MEDIA_REPEAT}, /* Recall */ { 0x44, KEY_MEDIA_REPEAT}, /* Recall */
{ 0xff00b54a, KEY_PAUSE }, /* Timeshift */ { 0x4a, KEY_PAUSE }, /* Timeshift */
{ 0xff00b847, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ { 0x47, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
{ 0xff00bc43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ { 0x43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
{ 0xff00b946, KEY_CHANNELUP }, { 0x46, KEY_CHANNELUP },
{ 0xff00bf40, KEY_CHANNELDOWN }, { 0x40, KEY_CHANNELDOWN },
{ 0xff00f708, KEY_ZOOM }, { 0x08, KEY_ZOOM },
{ 0xff00bd42, KEY_RECORD }, { 0x42, KEY_RECORD },
{ 0xff00a55a, KEY_STOP }, { 0x5a, KEY_STOP },
}; };
static struct rc_map_list lme2510_map = { static struct rc_map_list lme2510_map = {
.map = { .map = {
.scan = lme2510_rc, .scan = lme2510_rc,
.size = ARRAY_SIZE(lme2510_rc), .size = ARRAY_SIZE(lme2510_rc),
.rc_type = RC_TYPE_UNKNOWN, .rc_type = RC_TYPE_NEC,
.name = RC_MAP_LME2510, .name = RC_MAP_LME2510,
} }
}; };
......
...@@ -687,7 +687,7 @@ config VIDEO_HEXIUM_GEMINI ...@@ -687,7 +687,7 @@ config VIDEO_HEXIUM_GEMINI
config VIDEO_TIMBERDALE config VIDEO_TIMBERDALE
tristate "Support for timberdale Video In/LogiWIN" tristate "Support for timberdale Video In/LogiWIN"
depends on VIDEO_V4L2 && I2C depends on VIDEO_V4L2 && I2C && DMADEVICES
select DMA_ENGINE select DMA_ENGINE
select TIMB_DMA select TIMB_DMA
select VIDEO_ADV7180 select VIDEO_ADV7180
...@@ -757,6 +757,8 @@ config VIDEO_NOON010PC30 ...@@ -757,6 +757,8 @@ config VIDEO_NOON010PC30
---help--- ---help---
This driver supports NOON010PC30 CIF camera from Siliconfile This driver supports NOON010PC30 CIF camera from Siliconfile
source "drivers/media/video/m5mols/Kconfig"
config VIDEO_OMAP3 config VIDEO_OMAP3
tristate "OMAP 3 Camera support (EXPERIMENTAL)" tristate "OMAP 3 Camera support (EXPERIMENTAL)"
select OMAP_IOMMU select OMAP_IOMMU
...@@ -952,7 +954,7 @@ config VIDEO_SAMSUNG_S5P_FIMC ...@@ -952,7 +954,7 @@ config VIDEO_SAMSUNG_S5P_FIMC
config VIDEO_S5P_MIPI_CSIS config VIDEO_S5P_MIPI_CSIS
tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver"
depends on VIDEO_V4L2 && PM_RUNTIME && VIDEO_V4L2_SUBDEV_API depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API
---help--- ---help---
This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver.
......
...@@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o ...@@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
......
...@@ -438,7 +438,7 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v ...@@ -438,7 +438,7 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v
strcat(vc->card, " (676/"); strcat(vc->card, " (676/");
break; break;
default: default:
strcat(vc->card, " (???/"); strcat(vc->card, " (XXX/");
break; break;
} }
switch (cam->params.version.sensor_flags) { switch (cam->params.version.sensor_flags) {
...@@ -458,7 +458,7 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v ...@@ -458,7 +458,7 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v
strcat(vc->card, "500)"); strcat(vc->card, "500)");
break; break;
default: default:
strcat(vc->card, "???)"); strcat(vc->card, "XXX)");
break; break;
} }
......
...@@ -34,7 +34,7 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); ...@@ -34,7 +34,7 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifdef DEBUG #ifdef GSPCA_DEBUG
int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK | int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK |
D_USBI | D_USBO | D_V4L2; D_USBI | D_USBO | D_V4L2;
#endif #endif
......
config VIDEO_M5MOLS
tristate "Fujitsu M-5MOLS 8MP sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
---help---
This driver supports Fujitsu M-5MOLS camera sensor with ISP
m5mols-objs := m5mols_core.o m5mols_controls.o m5mols_capture.o
obj-$(CONFIG_VIDEO_M5MOLS) += m5mols.o
/*
* Header for M-5MOLS 8M Pixel camera sensor with ISP
*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
* Author: HeungJun Kim, riverful.kim@samsung.com
*
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef M5MOLS_H
#define M5MOLS_H
#include <media/v4l2-subdev.h>
#include "m5mols_reg.h"
extern int m5mols_debug;
#define to_m5mols(__sd) container_of(__sd, struct m5mols_info, sd)
#define to_sd(__ctrl) \
(&container_of(__ctrl->handler, struct m5mols_info, handle)->sd)
enum m5mols_restype {
M5MOLS_RESTYPE_MONITOR,
M5MOLS_RESTYPE_CAPTURE,
M5MOLS_RESTYPE_MAX,
};
/**
* struct m5mols_resolution - structure for the resolution
* @type: resolution type according to the pixel code
* @width: width of the resolution
* @height: height of the resolution
* @reg: resolution preset register value
*/
struct m5mols_resolution {
u8 reg;
enum m5mols_restype type;
u16 width;
u16 height;
};
/**
* struct m5mols_exif - structure for the EXIF information of M-5MOLS
* @exposure_time: exposure time register value
* @shutter_speed: speed of the shutter register value
* @aperture: aperture register value
* @exposure_bias: it calls also EV bias
* @iso_speed: ISO register value
* @flash: status register value of the flash
* @sdr: status register value of the Subject Distance Range
* @qval: not written exact meaning in document
*/
struct m5mols_exif {
u32 exposure_time;
u32 shutter_speed;
u32 aperture;
u32 brightness;
u32 exposure_bias;
u16 iso_speed;
u16 flash;
u16 sdr;
u16 qval;
};
/**
* struct m5mols_capture - Structure for the capture capability
* @exif: EXIF information
* @main: size in bytes of the main image
* @thumb: size in bytes of the thumb image, if it was accompanied
* @total: total size in bytes of the produced image
*/
struct m5mols_capture {
struct m5mols_exif exif;
u32 main;
u32 thumb;
u32 total;
};
/**
* struct m5mols_scenemode - structure for the scenemode capability
* @metering: metering light register value
* @ev_bias: EV bias register value
* @wb_mode: mode which means the WhiteBalance is Auto or Manual
* @wb_preset: whitebalance preset register value in the Manual mode
* @chroma_en: register value whether the Chroma capability is enabled or not
* @chroma_lvl: chroma's level register value
* @edge_en: register value Whether the Edge capability is enabled or not
* @edge_lvl: edge's level register value
* @af_range: Auto Focus's range
* @fd_mode: Face Detection mode
* @mcc: Multi-axis Color Conversion which means emotion color
* @light: status of the Light
* @flash: status of the Flash
* @tone: Tone color which means Contrast
* @iso: ISO register value
* @capt_mode: Mode of the Image Stabilization while the camera capturing
* @wdr: Wide Dynamic Range register value
*
* The each value according to each scenemode is recommended in the documents.
*/
struct m5mols_scenemode {
u32 metering;
u32 ev_bias;
u32 wb_mode;
u32 wb_preset;
u32 chroma_en;
u32 chroma_lvl;
u32 edge_en;
u32 edge_lvl;
u32 af_range;
u32 fd_mode;
u32 mcc;
u32 light;
u32 flash;
u32 tone;
u32 iso;
u32 capt_mode;
u32 wdr;
};
/**
* struct m5mols_version - firmware version information
* @customer: customer information
* @project: version of project information according to customer
* @fw: firmware revision
* @hw: hardware revision
* @param: version of the parameter
* @awb: Auto WhiteBalance algorithm version
* @str: information about manufacturer and packaging vendor
* @af: Auto Focus version
*
* The register offset starts the customer version at 0x0, and it ends
* the awb version at 0x09. The customer, project information occupies 1 bytes
* each. And also the fw, hw, param, awb each requires 2 bytes. The str is
* unique string associated with firmware's version. It includes information
* about manufacturer and the vendor of the sensor's packaging. The least
* significant 2 bytes of the string indicate packaging manufacturer.
*/
#define VERSION_STRING_SIZE 22
struct m5mols_version {
u8 customer;
u8 project;
u16 fw;
u16 hw;
u16 param;
u16 awb;
u8 str[VERSION_STRING_SIZE];
u8 af;
};
#define VERSION_SIZE sizeof(struct m5mols_version)
/**
* struct m5mols_info - M-5MOLS driver data structure
* @pdata: platform data
* @sd: v4l-subdev instance
* @pad: media pad
* @ffmt: current fmt according to resolution type
* @res_type: current resolution type
* @code: current code
* @irq_waitq: waitqueue for the capture
* @work_irq: workqueue for the IRQ
* @flags: state variable for the interrupt handler
* @handle: control handler
* @autoexposure: Auto Exposure control
* @exposure: Exposure control
* @autowb: Auto White Balance control
* @colorfx: Color effect control
* @saturation: Saturation control
* @zoom: Zoom control
* @ver: information of the version
* @cap: the capture mode attributes
* @power: current sensor's power status
* @ctrl_sync: true means all controls of the sensor are initialized
* @int_capture: true means the capture interrupt is issued once
* @lock_ae: true means the Auto Exposure is locked
* @lock_awb: true means the Aut WhiteBalance is locked
* @resolution: register value for current resolution
* @interrupt: register value for current interrupt status
* @mode: register value for current operation mode
* @mode_save: register value for current operation mode for saving
* @set_power: optional power callback to the board code
*/
struct m5mols_info {
const struct m5mols_platform_data *pdata;
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
int res_type;
enum v4l2_mbus_pixelcode code;
wait_queue_head_t irq_waitq;
struct work_struct work_irq;
unsigned long flags;
struct v4l2_ctrl_handler handle;
/* Autoexposure/exposure control cluster */
struct {
struct v4l2_ctrl *autoexposure;
struct v4l2_ctrl *exposure;
};
struct v4l2_ctrl *autowb;
struct v4l2_ctrl *colorfx;
struct v4l2_ctrl *saturation;
struct v4l2_ctrl *zoom;
struct m5mols_version ver;
struct m5mols_capture cap;
bool power;
bool ctrl_sync;
bool lock_ae;
bool lock_awb;
u8 resolution;
u32 interrupt;
u32 mode;
u32 mode_save;
int (*set_power)(struct device *dev, int on);
};
#define ST_CAPT_IRQ 0
#define is_powered(__info) (__info->power)
#define is_ctrl_synced(__info) (__info->ctrl_sync)
#define is_available_af(__info) (__info->ver.af)
#define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code)
#define is_manufacturer(__info, __manufacturer) \
(__info->ver.str[0] == __manufacturer[0] && \
__info->ver.str[1] == __manufacturer[1])
/*
* I2C operation of the M-5MOLS
*
* The I2C read operation of the M-5MOLS requires 2 messages. The first
* message sends the information about the command, command category, and total
* message size. The second message is used to retrieve the data specifed in
* the first message
*
* 1st message 2nd message
* +-------+---+----------+-----+-------+ +------+------+------+------+
* | size1 | R | category | cmd | size2 | | d[0] | d[1] | d[2] | d[3] |
* +-------+---+----------+-----+-------+ +------+------+------+------+
* - size1: message data size(5 in this case)
* - size2: desired buffer size of the 2nd message
* - d[0..3]: according to size2
*
* The I2C write operation needs just one message. The message includes
* category, command, total size, and desired data.
*
* 1st message
* +-------+---+----------+-----+------+------+------+------+
* | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] |
* +-------+---+----------+-----+------+------+------+------+
* - d[0..3]: according to size1
*/
int m5mols_read(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value);
/*
* Mode operation of the M-5MOLS
*
* Changing the mode of the M-5MOLS is needed right executing order.
* There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed
* by user. There are various categories associated with each mode.
*
* +============================================================+
* | mode | category |
* +============================================================+
* | FLASH | FLASH(only after Stand-by or Power-on) |
* | SYSTEM | SYSTEM(only after sensor arm-booting) |
* | PARAMETER | PARAMETER |
* | MONITOR | MONITOR(preview), Auto Focus, Face Detection |
* | CAPTURE | Single CAPTURE, Preview(recording) |
* +============================================================+
*
* The available executing order between each modes are as follows:
* PARAMETER <---> MONITOR <---> CAPTURE
*/
int m5mols_mode(struct m5mols_info *info, u32 mode);
int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg);
int m5mols_sync_controls(struct m5mols_info *info);
int m5mols_start_capture(struct m5mols_info *info);
int m5mols_do_scenemode(struct m5mols_info *info, u32 mode);
int m5mols_lock_3a(struct m5mols_info *info, bool lock);
int m5mols_set_ctrl(struct v4l2_ctrl *ctrl);
/* The firmware function */
int m5mols_update_fw(struct v4l2_subdev *sd,
int (*set_power)(struct m5mols_info *, bool));
#endif /* M5MOLS_H */
/*
* The Capture code for Fujitsu M-5MOLS ISP
*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
* Author: HeungJun Kim, riverful.kim@samsung.com
*
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/videodev2.h>
#include <linux/version.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include <media/m5mols.h>
#include "m5mols.h"
#include "m5mols_reg.h"
static int m5mols_capture_error_handler(struct m5mols_info *info,
int timeout)
{
int ret;
/* Disable all interrupts and clear relevant interrupt staus bits */
ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE,
info->interrupt & ~(REG_INT_CAPTURE));
if (ret)
return ret;
if (timeout == 0)
return -ETIMEDOUT;
return 0;
}
/**
* m5mols_read_rational - I2C read of a rational number
*
* Read numerator and denominator from registers @addr_num and @addr_den
* respectively and return the division result in @val.
*/
static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num,
u32 addr_den, u32 *val)
{
u32 num, den;
int ret = m5mols_read(sd, addr_num, &num);
if (!ret)
ret = m5mols_read(sd, addr_den, &den);
if (ret)
return ret;
*val = den == 0 ? 0 : num / den;
return ret;
}
/**
* m5mols_capture_info - Gather captured image information
*
* For now it gathers only EXIF information and file size.
*/
static int m5mols_capture_info(struct m5mols_info *info)
{
struct m5mols_exif *exif = &info->cap.exif;
struct v4l2_subdev *sd = &info->sd;
int ret;
ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU,
EXIF_INFO_EXPTIME_DE, &exif->exposure_time);
if (ret)
return ret;
ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE,
&exif->shutter_speed);
if (ret)
return ret;
ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE,
&exif->aperture);
if (ret)
return ret;
ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE,
&exif->brightness);
if (ret)
return ret;
ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE,
&exif->exposure_bias);
if (ret)
return ret;
ret = m5mols_read(sd, EXIF_INFO_ISO, (u32 *)&exif->iso_speed);
if (!ret)
ret = m5mols_read(sd, EXIF_INFO_FLASH, (u32 *)&exif->flash);
if (!ret)
ret = m5mols_read(sd, EXIF_INFO_SDR, (u32 *)&exif->sdr);
if (!ret)
ret = m5mols_read(sd, EXIF_INFO_QVAL, (u32 *)&exif->qval);
if (ret)
return ret;
if (!ret)
ret = m5mols_read(sd, CAPC_IMAGE_SIZE, &info->cap.main);
if (!ret)
ret = m5mols_read(sd, CAPC_THUMB_SIZE, &info->cap.thumb);
if (!ret)
info->cap.total = info->cap.main + info->cap.thumb;
return ret;
}
int m5mols_start_capture(struct m5mols_info *info)
{
struct v4l2_subdev *sd = &info->sd;
u32 resolution = info->resolution;
int timeout;
int ret;
/*
* Preparing capture. Setting control & interrupt before entering
* capture mode
*
* 1) change to MONITOR mode for operating control & interrupt
* 2) set controls (considering v4l2_control value & lock 3A)
* 3) set interrupt
* 4) change to CAPTURE mode
*/
ret = m5mols_mode(info, REG_MONITOR);
if (!ret)
ret = m5mols_sync_controls(info);
if (!ret)
ret = m5mols_lock_3a(info, true);
if (!ret)
ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
if (!ret)
ret = m5mols_mode(info, REG_CAPTURE);
if (!ret) {
/* Wait for capture interrupt, after changing capture mode */
timeout = wait_event_interruptible_timeout(info->irq_waitq,
test_bit(ST_CAPT_IRQ, &info->flags),
msecs_to_jiffies(2000));
if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags))
ret = m5mols_capture_error_handler(info, timeout);
}
if (!ret)
ret = m5mols_lock_3a(info, false);
if (ret)
return ret;
/*
* Starting capture. Setting capture frame count and resolution and
* the format(available format: JPEG, Bayer RAW, YUV).
*
* 1) select single or multi(enable to 25), format, size
* 2) set interrupt
* 3) start capture(for main image, now)
* 4) get information
* 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device)
*/
ret = m5mols_write(sd, CAPC_SEL_FRAME, 1);
if (!ret)
ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
if (!ret)
ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution);
if (!ret)
ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
if (!ret)
ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);
if (!ret) {
/* Wait for the capture completion interrupt */
timeout = wait_event_interruptible_timeout(info->irq_waitq,
test_bit(ST_CAPT_IRQ, &info->flags),
msecs_to_jiffies(2000));
if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) {
ret = m5mols_capture_info(info);
if (!ret)
v4l2_subdev_notify(sd, 0, &info->cap.total);
}
}
return m5mols_capture_error_handler(info, timeout);
}
/*
* Controls for M-5MOLS 8M Pixel camera sensor with ISP
*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
* Author: HeungJun Kim, riverful.kim@samsung.com
*
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <media/v4l2-ctrls.h>
#include "m5mols.h"
#include "m5mols_reg.h"
static struct m5mols_scenemode m5mols_default_scenemode[] = {
[REG_SCENE_NORMAL] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF,
5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_PORTRAIT] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 3, REG_EDGE_ON, 4,
REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_LANDSCAPE] = {
REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 4, REG_EDGE_ON, 6,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_SPORTS] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_PARTY_INDOOR] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_BEACH_SNOW] = {
REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_SUNSET] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
REG_AWB_DAYLIGHT,
REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_DAWN_DUSK] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
REG_AWB_FLUORESCENT_1,
REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_FALL] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 5, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_NIGHT] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_AGAINST_LIGHT] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_FIRE] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
},
[REG_SCENE_TEXT] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 3, REG_EDGE_ON, 7,
REG_AF_MACRO, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON,
},
[REG_SCENE_CANDLE] = {
REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
REG_AF_NORMAL, REG_FD_OFF,
REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
},
};
/**
* m5mols_do_scenemode() - Change current scenemode
* @mode: Desired mode of the scenemode
*
* WARNING: The execution order is important. Do not change the order.
*/
int m5mols_do_scenemode(struct m5mols_info *info, u32 mode)
{
struct v4l2_subdev *sd = &info->sd;
struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];
int ret;
if (mode > REG_SCENE_CANDLE)
return -EINVAL;
ret = m5mols_lock_3a(info, false);
if (!ret)
ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);
if (!ret)
ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode);
if (!ret)
ret = m5mols_write(sd, AE_MODE, scenemode.metering);
if (!ret)
ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias);
if (!ret)
ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode);
if (!ret)
ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset);
if (!ret)
ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en);
if (!ret)
ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl);
if (!ret)
ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en);
if (!ret)
ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl);
if (!ret && is_available_af(info))
ret = m5mols_write(sd, AF_MODE, scenemode.af_range);
if (!ret && is_available_af(info))
ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode);
if (!ret)
ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone);
if (!ret)
ret = m5mols_write(sd, AE_ISO, scenemode.iso);
if (!ret)
ret = m5mols_mode(info, REG_CAPTURE);
if (!ret)
ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr);
if (!ret)
ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc);
if (!ret)
ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light);
if (!ret)
ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash);
if (!ret)
ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode);
if (!ret)
ret = m5mols_mode(info, REG_MONITOR);
return ret;
}
static int m5mols_lock_ae(struct m5mols_info *info, bool lock)
{
int ret = 0;
if (info->lock_ae != lock)
ret = m5mols_write(&info->sd, AE_LOCK,
lock ? REG_AE_LOCK : REG_AE_UNLOCK);
if (!ret)
info->lock_ae = lock;
return ret;
}
static int m5mols_lock_awb(struct m5mols_info *info, bool lock)
{
int ret = 0;
if (info->lock_awb != lock)
ret = m5mols_write(&info->sd, AWB_LOCK,
lock ? REG_AWB_LOCK : REG_AWB_UNLOCK);
if (!ret)
info->lock_awb = lock;
return ret;
}
/* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */
int m5mols_lock_3a(struct m5mols_info *info, bool lock)
{
int ret;
ret = m5mols_lock_ae(info, lock);
if (!ret)
ret = m5mols_lock_awb(info, lock);
/* Don't need to handle unlocking AF */
if (!ret && is_available_af(info) && lock)
ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
return ret;
}
/* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */
int m5mols_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = to_sd(ctrl);
struct m5mols_info *info = to_m5mols(sd);
int ret;
switch (ctrl->id) {
case V4L2_CID_ZOOM_ABSOLUTE:
return m5mols_write(sd, MON_ZOOM, ctrl->val);
case V4L2_CID_EXPOSURE_AUTO:
ret = m5mols_lock_ae(info,
ctrl->val == V4L2_EXPOSURE_AUTO ? false : true);
if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO)
ret = m5mols_write(sd, AE_MODE, REG_AE_ALL);
if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) {
int val = info->exposure->val;
ret = m5mols_write(sd, AE_MODE, REG_AE_OFF);
if (!ret)
ret = m5mols_write(sd, AE_MAN_GAIN_MON, val);
if (!ret)
ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val);
}
return ret;
case V4L2_CID_AUTO_WHITE_BALANCE:
ret = m5mols_lock_awb(info, ctrl->val ? false : true);
if (!ret)
ret = m5mols_write(sd, AWB_MODE, ctrl->val ?
REG_AWB_AUTO : REG_AWB_PRESET);
return ret;
case V4L2_CID_SATURATION:
ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val);
if (!ret)
ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON);
return ret;
case V4L2_CID_COLORFX:
/*
* This control uses two kinds of registers: normal & color.
* The normal effect belongs to category 1, while the color
* one belongs to category 2.
*
* The normal effect uses one register: CAT1_EFFECT.
* The color effect uses three registers:
* CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB.
*/
ret = m5mols_write(sd, PARM_EFFECT,
ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA :
ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS :
REG_EFFECT_OFF);
if (!ret)
ret = m5mols_write(sd, MON_EFFECT,
ctrl->val == V4L2_COLORFX_SEPIA ?
REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF);
if (!ret)
ret = m5mols_write(sd, MON_CFIXR,
ctrl->val == V4L2_COLORFX_SEPIA ?
REG_CFIXR_SEPIA : 0);
if (!ret)
ret = m5mols_write(sd, MON_CFIXB,
ctrl->val == V4L2_COLORFX_SEPIA ?
REG_CFIXB_SEPIA : 0);
return ret;
}
return -EINVAL;
}
This diff is collapsed.
This diff is collapsed.
uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
uvc_status.o uvc_isight.o uvc_status.o uvc_isight.o
ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
uvcvideo-objs += uvc_entity.o
endif
obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o
...@@ -248,7 +248,7 @@ uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator) ...@@ -248,7 +248,7 @@ uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
* Terminal and unit management * Terminal and unit management
*/ */
static struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
{ {
struct uvc_entity *entity; struct uvc_entity *entity;
...@@ -795,9 +795,12 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, ...@@ -795,9 +795,12 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
struct uvc_entity *entity; struct uvc_entity *entity;
unsigned int num_inputs; unsigned int num_inputs;
unsigned int size; unsigned int size;
unsigned int i;
extra_size = ALIGN(extra_size, sizeof(*entity->pads));
num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
size = sizeof(*entity) + extra_size + num_inputs; size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
+ num_inputs;
entity = kzalloc(size, GFP_KERNEL); entity = kzalloc(size, GFP_KERNEL);
if (entity == NULL) if (entity == NULL)
return NULL; return NULL;
...@@ -805,8 +808,17 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, ...@@ -805,8 +808,17 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
entity->id = id; entity->id = id;
entity->type = type; entity->type = type;
entity->num_links = 0;
entity->num_pads = num_pads;
entity->pads = ((void *)(entity + 1)) + extra_size;
for (i = 0; i < num_inputs; ++i)
entity->pads[i].flags = MEDIA_PAD_FL_SINK;
if (!UVC_ENTITY_IS_OTERM(entity))
entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE;
entity->bNrInPins = num_inputs; entity->bNrInPins = num_inputs;
entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size; entity->baSourceID = (__u8 *)(&entity->pads[num_pads]);
return entity; return entity;
} }
...@@ -1585,6 +1597,13 @@ static void uvc_delete(struct uvc_device *dev) ...@@ -1585,6 +1597,13 @@ static void uvc_delete(struct uvc_device *dev)
uvc_status_cleanup(dev); uvc_status_cleanup(dev);
uvc_ctrl_cleanup_device(dev); uvc_ctrl_cleanup_device(dev);
if (dev->vdev.dev)
v4l2_device_unregister(&dev->vdev);
#ifdef CONFIG_MEDIA_CONTROLLER
if (media_devnode_is_registered(&dev->mdev.devnode))
media_device_unregister(&dev->mdev);
#endif
list_for_each_safe(p, n, &dev->chains) { list_for_each_safe(p, n, &dev->chains) {
struct uvc_video_chain *chain; struct uvc_video_chain *chain;
chain = list_entry(p, struct uvc_video_chain, list); chain = list_entry(p, struct uvc_video_chain, list);
...@@ -1594,6 +1613,13 @@ static void uvc_delete(struct uvc_device *dev) ...@@ -1594,6 +1613,13 @@ static void uvc_delete(struct uvc_device *dev)
list_for_each_safe(p, n, &dev->entities) { list_for_each_safe(p, n, &dev->entities) {
struct uvc_entity *entity; struct uvc_entity *entity;
entity = list_entry(p, struct uvc_entity, list); entity = list_entry(p, struct uvc_entity, list);
#ifdef CONFIG_MEDIA_CONTROLLER
uvc_mc_cleanup_entity(entity);
#endif
if (entity->vdev) {
video_device_release(entity->vdev);
entity->vdev = NULL;
}
kfree(entity); kfree(entity);
} }
...@@ -1616,8 +1642,6 @@ static void uvc_release(struct video_device *vdev) ...@@ -1616,8 +1642,6 @@ static void uvc_release(struct video_device *vdev)
struct uvc_streaming *stream = video_get_drvdata(vdev); struct uvc_streaming *stream = video_get_drvdata(vdev);
struct uvc_device *dev = stream->dev; struct uvc_device *dev = stream->dev;
video_device_release(vdev);
/* Decrement the registered streams count and delete the device when it /* Decrement the registered streams count and delete the device when it
* reaches zero. * reaches zero.
*/ */
...@@ -1682,7 +1706,7 @@ static int uvc_register_video(struct uvc_device *dev, ...@@ -1682,7 +1706,7 @@ static int uvc_register_video(struct uvc_device *dev,
* unregistered before the reference is released, so we don't need to * unregistered before the reference is released, so we don't need to
* get another one. * get another one.
*/ */
vdev->parent = &dev->intf->dev; vdev->v4l2_dev = &dev->vdev;
vdev->fops = &uvc_fops; vdev->fops = &uvc_fops;
vdev->release = uvc_release; vdev->release = uvc_release;
strlcpy(vdev->name, dev->name, sizeof vdev->name); strlcpy(vdev->name, dev->name, sizeof vdev->name);
...@@ -1731,6 +1755,8 @@ static int uvc_register_terms(struct uvc_device *dev, ...@@ -1731,6 +1755,8 @@ static int uvc_register_terms(struct uvc_device *dev,
ret = uvc_register_video(dev, stream); ret = uvc_register_video(dev, stream);
if (ret < 0) if (ret < 0)
return ret; return ret;
term->vdev = stream->vdev;
} }
return 0; return 0;
...@@ -1745,6 +1771,14 @@ static int uvc_register_chains(struct uvc_device *dev) ...@@ -1745,6 +1771,14 @@ static int uvc_register_chains(struct uvc_device *dev)
ret = uvc_register_terms(dev, chain); ret = uvc_register_terms(dev, chain);
if (ret < 0) if (ret < 0)
return ret; return ret;
#ifdef CONFIG_MEDIA_CONTROLLER
ret = uvc_mc_register_entities(chain);
if (ret < 0) {
uvc_printk(KERN_INFO, "Failed to register entites "
"(%d).\n", ret);
}
#endif
} }
return 0; return 0;
...@@ -1814,6 +1848,24 @@ static int uvc_probe(struct usb_interface *intf, ...@@ -1814,6 +1848,24 @@ static int uvc_probe(struct usb_interface *intf,
"linux-uvc-devel mailing list.\n"); "linux-uvc-devel mailing list.\n");
} }
/* Register the media and V4L2 devices. */
#ifdef CONFIG_MEDIA_CONTROLLER
dev->mdev.dev = &intf->dev;
strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
if (udev->serial)
strlcpy(dev->mdev.serial, udev->serial,
sizeof(dev->mdev.serial));
strcpy(dev->mdev.bus_info, udev->devpath);
dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
dev->mdev.driver_version = DRIVER_VERSION_NUMBER;
if (media_device_register(&dev->mdev) < 0)
goto error;
dev->vdev.mdev = &dev->mdev;
#endif
if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
goto error;
/* Initialize controls. */ /* Initialize controls. */
if (uvc_ctrl_init_device(dev) < 0) if (uvc_ctrl_init_device(dev) < 0)
goto error; goto error;
...@@ -1822,7 +1874,7 @@ static int uvc_probe(struct usb_interface *intf, ...@@ -1822,7 +1874,7 @@ static int uvc_probe(struct usb_interface *intf,
if (uvc_scan_device(dev) < 0) if (uvc_scan_device(dev) < 0)
goto error; goto error;
/* Register video devices. */ /* Register video device nodes. */
if (uvc_register_chains(dev) < 0) if (uvc_register_chains(dev) < 0)
goto error; goto error;
......
/*
* uvc_entity.c -- USB Video Class driver
*
* Copyright (C) 2005-2011
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include "uvcvideo.h"
/* ------------------------------------------------------------------------
* Video subdevices registration and unregistration
*/
static int uvc_mc_register_entity(struct uvc_video_chain *chain,
struct uvc_entity *entity)
{
const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
struct uvc_entity *remote;
unsigned int i;
u8 remote_pad;
int ret;
for (i = 0; i < entity->num_pads; ++i) {
struct media_entity *source;
struct media_entity *sink;
if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK))
continue;
remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]);
if (remote == NULL)
return -EINVAL;
source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
? &remote->vdev->entity : &remote->subdev.entity;
sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
? &entity->vdev->entity : &entity->subdev.entity;
remote_pad = remote->num_pads - 1;
ret = media_entity_create_link(source, remote_pad,
sink, i, flags);
if (ret < 0)
return ret;
}
if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING)
ret = v4l2_device_register_subdev(&chain->dev->vdev,
&entity->subdev);
return ret;
}
static struct v4l2_subdev_ops uvc_subdev_ops = {
};
void uvc_mc_cleanup_entity(struct uvc_entity *entity)
{
if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING)
media_entity_cleanup(&entity->subdev.entity);
else if (entity->vdev != NULL)
media_entity_cleanup(&entity->vdev->entity);
}
static int uvc_mc_init_entity(struct uvc_entity *entity)
{
int ret;
if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) {
v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops);
strlcpy(entity->subdev.name, entity->name,
sizeof(entity->subdev.name));
ret = media_entity_init(&entity->subdev.entity,
entity->num_pads, entity->pads, 0);
} else
ret = media_entity_init(&entity->vdev->entity,
entity->num_pads, entity->pads, 0);
return ret;
}
int uvc_mc_register_entities(struct uvc_video_chain *chain)
{
struct uvc_entity *entity;
int ret;
list_for_each_entry(entity, &chain->entities, chain) {
ret = uvc_mc_init_entity(entity);
if (ret < 0) {
uvc_printk(KERN_INFO, "Failed to initialize entity for "
"entity %u\n", entity->id);
return ret;
}
}
list_for_each_entry(entity, &chain->entities, chain) {
ret = uvc_mc_register_entity(chain, entity);
if (ret < 0) {
uvc_printk(KERN_INFO, "Failed to register entity for "
"entity %u\n", entity->id);
return ret;
}
}
return 0;
}
...@@ -98,8 +98,11 @@ struct uvc_xu_control { ...@@ -98,8 +98,11 @@ struct uvc_xu_control {
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/usb.h>
#include <linux/usb/video.h> #include <linux/usb/video.h>
#include <linux/uvcvideo.h> #include <linux/uvcvideo.h>
#include <media/media-device.h>
#include <media/v4l2-device.h>
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
* UVC constants * UVC constants
...@@ -301,6 +304,13 @@ struct uvc_entity { ...@@ -301,6 +304,13 @@ struct uvc_entity {
__u16 type; __u16 type;
char name[64]; char name[64];
/* Media controller-related fields. */
struct video_device *vdev;
struct v4l2_subdev subdev;
unsigned int num_pads;
unsigned int num_links;
struct media_pad *pads;
union { union {
struct { struct {
__u16 wObjectiveFocalLengthMin; __u16 wObjectiveFocalLengthMin;
...@@ -504,6 +514,10 @@ struct uvc_device { ...@@ -504,6 +514,10 @@ struct uvc_device {
atomic_t nmappings; atomic_t nmappings;
/* Video control interface */ /* Video control interface */
#ifdef CONFIG_MEDIA_CONTROLLER
struct media_device mdev;
#endif
struct v4l2_device vdev;
__u16 uvc_version; __u16 uvc_version;
__u32 clock_frequency; __u32 clock_frequency;
...@@ -583,6 +597,8 @@ extern unsigned int uvc_timeout_param; ...@@ -583,6 +597,8 @@ extern unsigned int uvc_timeout_param;
/* Core driver */ /* Core driver */
extern struct uvc_driver uvc_driver; extern struct uvc_driver uvc_driver;
extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
/* Video buffers queue management. */ /* Video buffers queue management. */
extern void uvc_queue_init(struct uvc_video_queue *queue, extern void uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type, int drop_corrupted); enum v4l2_buf_type type, int drop_corrupted);
...@@ -616,6 +632,10 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) ...@@ -616,6 +632,10 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
/* V4L2 interface */ /* V4L2 interface */
extern const struct v4l2_file_operations uvc_fops; extern const struct v4l2_file_operations uvc_fops;
/* Media controller */
extern int uvc_mc_register_entities(struct uvc_video_chain *chain);
extern void uvc_mc_cleanup_entity(struct uvc_entity *entity);
/* Video */ /* Video */
extern int uvc_video_init(struct uvc_streaming *stream); extern int uvc_video_init(struct uvc_streaming *stream);
extern int uvc_video_suspend(struct uvc_streaming *stream); extern int uvc_video_suspend(struct uvc_streaming *stream);
......
/*
* Driver header for M-5MOLS 8M Pixel camera sensor with ISP
*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
* Author: HeungJun Kim, riverful.kim@samsung.com
*
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef MEDIA_M5MOLS_H
#define MEDIA_M5MOLS_H
/**
* struct m5mols_platform_data - platform data for M-5MOLS driver
* @irq: GPIO getting the irq pin of M-5MOLS
* @gpio_reset: GPIO driving the reset pin of M-5MOLS
* @reset_polarity: active state for gpio_rst pin, 0 or 1
* @set_power: an additional callback to the board setup code
* to be called after enabling and before disabling
* the sensor's supply regulators
*/
struct m5mols_platform_data {
int irq;
int gpio_reset;
u8 reset_polarity;
int (*set_power)(struct device *dev, int on);
};
#endif /* MEDIA_M5MOLS_H */
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include <dvb_net.h> #include <dvb_net.h>
#include <dvb_frontend.h> #include <dvb_frontend.h>
#ifndef _VIDEOBUF_DVB_H_
#define _VIDEOBUF_DVB_H_
struct videobuf_dvb { struct videobuf_dvb {
/* filling that the job of the driver */ /* filling that the job of the driver */
char *name; char *name;
...@@ -54,6 +57,7 @@ void videobuf_dvb_dealloc_frontends(struct videobuf_dvb_frontends *f); ...@@ -54,6 +57,7 @@ void videobuf_dvb_dealloc_frontends(struct videobuf_dvb_frontends *f);
struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id); struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id);
int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p); int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p);
#endif /* _VIDEOBUF_DVB_H_ */
/* /*
* Local variables: * Local variables:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment