From 03bcc8695fb4334e4e30d03a9dc0867361615c1a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 16 Feb 2009 15:27:44 -0300 Subject: Revert changeset aa3e5cc1d833 From: Mauro Carvalho Chehab On Mon, 02 Feb 2009, Hartmut wrote: This change set is wrong. The affected functions cannot be called from an interrupt context, because they may process large buffers. In this case, interrupts are disabled for a long time. Functions, like dvb_dmx_swfilter_packets(), could be called only from a tasklet. This change set does hide some strong design bugs in dm1105.c and au0828-dvb.c. Please revert this change set and do fix the bugs in dm1105.c and au0828-dvb.c (and other files). On Sun, 15 Feb 2009, Oliver Endriss wrote: This changeset _must_ be reverted! It breaks all kernels since 2.6.27 for applications which use DVB and require a low interrupt latency. It is a very bad idea to call the demuxer to process data buffers with interrupts disabled! On Mon, 16 Feb 2009, Trent Piepho wrote: I agree, this is bad. The demuxer is far too much work to be done with IRQs off. IMHO, even doing it under a spin-lock is excessive. It should be a mutex. Drivers should use a work-queue to feed the demuxer. Thank you for testing this changeset and discovering the issues on it. Priority: high CC: Trent Piepho CC: Hartmut CC: Oliver Endriss CC: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dmxdev.c | 16 +++++++--------- linux/drivers/media/dvb/dvb-core/dvb_demux.c | 16 ++++++---------- 2 files changed, 13 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.c b/linux/drivers/media/dvb/dvb-core/dmxdev.c index cc143929a..c35fbb8d8 100644 --- a/linux/drivers/media/dvb/dvb-core/dmxdev.c +++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c @@ -364,16 +364,15 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, enum dmx_success success) { struct dmxdev_filter *dmxdevfilter = filter->priv; - unsigned long flags; int ret; if (dmxdevfilter->buffer.error) { wake_up(&dmxdevfilter->buffer.queue); return 0; } - spin_lock_irqsave(&dmxdevfilter->dev->lock, flags); + spin_lock(&dmxdevfilter->dev->lock); if (dmxdevfilter->state != DMXDEV_STATE_GO) { - spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); + spin_unlock(&dmxdevfilter->dev->lock); return 0; } del_timer(&dmxdevfilter->timer); @@ -392,7 +391,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, } if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) dmxdevfilter->state = DMXDEV_STATE_DONE; - spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); + spin_unlock(&dmxdevfilter->dev->lock); wake_up(&dmxdevfilter->buffer.queue); return 0; } @@ -404,12 +403,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, { struct dmxdev_filter *dmxdevfilter = feed->priv; struct dvb_ringbuffer *buffer; - unsigned long flags; int ret; - spin_lock_irqsave(&dmxdevfilter->dev->lock, flags); + spin_lock(&dmxdevfilter->dev->lock); if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { - spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); + spin_unlock(&dmxdevfilter->dev->lock); return 0; } @@ -419,7 +417,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, else buffer = &dmxdevfilter->dev->dvr_buffer; if (buffer->error) { - spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); + spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); return 0; } @@ -430,7 +428,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, dvb_ringbuffer_flush(buffer); buffer->error = ret; } - spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); + spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); return 0; } diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.c b/linux/drivers/media/dvb/dvb-core/dvb_demux.c index a2c1fd5d2..e2eca0b1f 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.c @@ -399,9 +399,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count) { - unsigned long flags; - - spin_lock_irqsave(&demux->lock, flags); + spin_lock(&demux->lock); while (count--) { if (buf[0] == 0x47) @@ -409,17 +407,16 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, buf += 188; } - spin_unlock_irqrestore(&demux->lock, flags); + spin_unlock(&demux->lock); } EXPORT_SYMBOL(dvb_dmx_swfilter_packets); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) { - unsigned long flags; int p = 0, i, j; - spin_lock_irqsave(&demux->lock, flags); + spin_lock(&demux->lock); if (demux->tsbufp) { i = demux->tsbufp; @@ -452,18 +449,17 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) } bailout: - spin_unlock_irqrestore(&demux->lock, flags); + spin_unlock(&demux->lock); } EXPORT_SYMBOL(dvb_dmx_swfilter); void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) { - unsigned long flags; int p = 0, i, j; u8 tmppack[188]; - spin_lock_irqsave(&demux->lock, flags); + spin_lock(&demux->lock); if (demux->tsbufp) { i = demux->tsbufp; @@ -504,7 +500,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) } bailout: - spin_unlock_irqrestore(&demux->lock, flags); + spin_unlock(&demux->lock); } EXPORT_SYMBOL(dvb_dmx_swfilter_204); -- cgit v1.2.3 From 7c429cdbe8e7fa93d0c24d10749fe2a2bdd5e524 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 15 Jan 2009 21:58:55 +0900 Subject: saa7134: fix Avermedia E506R composite input From: Tim Farrington Make correction to composite input plus svideo input to Avermedia E506R Signed-off-by: Tim Farrington Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 01cc9543f..e565d437b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4362,13 +4362,13 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, .tv = 1, }, { - .name = name_comp, - .vmux = 0, + .name = name_comp1, + .vmux = 3, .amux = LINE1, }, { .name = name_svideo, .vmux = 8, - .amux = LINE1, + .amux = LINE2, } }, .radio = { .name = name_radio, -- cgit v1.2.3 From cc7185f96b8e9132c28118367f6c84569939c37d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 16 Dec 2008 00:56:08 -0500 Subject: sms1xxx: enable rf switch on Hauppauge Tiger devices From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/sms-cards.c | 23 +++++++++++++++++++++-- linux/drivers/media/dvb/siano/sms-cards.h | 3 ++- linux/drivers/media/dvb/siano/smsdvb.c | 19 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 79f5715c0..6c8faeb74 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -117,6 +117,7 @@ static struct sms_board sms_boards[] = { .type = SMS_NOVA_B0, .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", .lna_ctrl = 29, + .rf_switch = 17, }, [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { .name = "Hauppauge WinTV MiniCard", @@ -199,8 +200,8 @@ int sms_board_power(struct smscore_device_t *coredev, int onoff) case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: /* LNA */ - sms_set_gpio(coredev, - board->lna_ctrl, onoff ? 1 : 0); + if (!onoff) + sms_set_gpio(coredev, board->lna_ctrl, 0); break; } return 0; @@ -227,3 +228,21 @@ int sms_board_led_feedback(struct smscore_device_t *coredev, int led) } return 0; } + +int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) +{ + int board_id = smscore_get_board_id(coredev); + struct sms_board *board = sms_get_board(board_id); + + sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled"); + + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: + sms_set_gpio(coredev, + board->rf_switch, onoff ? 1 : 0); + return sms_set_gpio(coredev, + board->lna_ctrl, onoff ? 1 : 0); + } + return -EINVAL; +} diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h index 8e0fe9fd2..fe292aaea 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.h +++ b/linux/drivers/media/dvb/siano/sms-cards.h @@ -40,7 +40,7 @@ struct sms_board { char *name, *fw[DEVICE_MODE_MAX]; /* gpios */ - int led_power, led_hi, led_lo, lna_ctrl; + int led_power, led_hi, led_lo, lna_ctrl, rf_switch; }; struct sms_board *sms_get_board(int id); @@ -52,6 +52,7 @@ int sms_board_setup(struct smscore_device_t *coredev); #define SMS_LED_HI 2 int sms_board_led_feedback(struct smscore_device_t *coredev, int led); int sms_board_power(struct smscore_device_t *coredev, int onoff); +int sms_board_lna_control(struct smscore_device_t *coredev, int onoff); extern struct usb_device_id smsusb_id_table[]; diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index bbc87fe2e..a2efb402e 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -262,6 +262,7 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, struct SmsMsgHdr_ST Msg; u32 Data[3]; } Msg; + int ret; Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; Msg.Msg.msgDstId = HIF_TASK; @@ -285,6 +286,24 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, default: return -EINVAL; } + /* Disable LNA, if any. An error is returned if no LNA is present */ + ret = sms_board_lna_control(client->coredev, 0); + if (ret == 0) { + fe_status_t status; + + /* tune with LNA off at first */ + ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), + &client->tune_done); + + smsdvb_read_status(fe, &status); + + if (status & FE_HAS_LOCK) + return ret; + + /* previous tune didnt lock - enable LNA and tune again */ + sms_board_lna_control(client->coredev, 1); + } + return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->tune_done); } -- cgit v1.2.3 From 5180a035b637308ddd873e58c46fdedbecb061f6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 31 Aug 2008 16:15:47 -0400 Subject: sms1xxx: move definition of struct smsdvb_client_t into smsdvb.c From: Michael Krufky Nobody uses struct smsdvb_client_t other than smsdvb.c -- this does not need to be inside smscoreapi.h Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/smscoreapi.h | 21 --------------------- linux/drivers/media/dvb/siano/smsdvb.c | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 1ab277767..0469f1bd8 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -523,27 +523,6 @@ struct smscore_gpio_config { u8 outputdriving; }; -struct smsdvb_client_t { - struct list_head entry; - - struct smscore_device_t *coredev; - struct smscore_client_t *smsclient; - - struct dvb_adapter adapter; - struct dvb_demux demux; - struct dmxdev dmxdev; - struct dvb_frontend frontend; - - fe_status_t fe_status; - int fe_ber, fe_snr, fe_unc, fe_signal_strength; - - struct completion tune_done, stat_done; - - /* todo: save freq/band instead whole struct */ - struct dvb_frontend_parameters fe_params; - -}; - extern void smscore_registry_setmode(char *devpath, int mode); extern int smscore_registry_getmode(char *devpath); diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index a2efb402e..68f3f31bb 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -27,6 +27,26 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +struct smsdvb_client_t { + struct list_head entry; + + struct smscore_device_t *coredev; + struct smscore_client_t *smsclient; + + struct dvb_adapter adapter; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dvb_frontend frontend; + + fe_status_t fe_status; + int fe_ber, fe_snr, fe_unc, fe_signal_strength; + + struct completion tune_done, stat_done; + + /* todo: save freq/band instead whole struct */ + struct dvb_frontend_parameters fe_params; +}; + static struct list_head g_smsdvb_clients; static struct mutex g_smsdvb_clientslock; -- cgit v1.2.3 From c058193ee17449d1cb5e4685cab530b95bbb2b1b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 30 Aug 2008 23:44:04 -0400 Subject: sms1xxx: restore smsusb_driver.name to smsusb From: Uri Shkolnik The sms1xxx driver will be broken down into smaller modules, so the original name, smsusb, is more appropriate. Signed-off-by: Uri Shkolnik Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/smsusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index fd191b0ef..7a04b34b0 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -479,7 +479,7 @@ static int smsusb_resume(struct usb_interface *intf) } static struct usb_driver smsusb_driver = { - .name = "sms1xxx", + .name = "smsusb", .probe = smsusb_probe, .disconnect = smsusb_disconnect, .id_table = smsusb_id_table, -- cgit v1.2.3 From ddc98ba47b865fb467edeb186cb64ae65d608e26 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 31 Aug 2008 16:03:15 -0400 Subject: sms1xxx: move smsusb_id_table into smsusb.c From: Michael Krufky Move the usb_device_id table to the smsusb module in preparation for the sms1xxx module to be split into sub-modules. This will allow the smsusb driver to start up automatically upon insertion of the USB device. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/sms-cards.c | 47 ------------------------------- linux/drivers/media/dvb/siano/sms-cards.h | 2 -- linux/drivers/media/dvb/siano/smsusb.c | 47 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 49 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 6c8faeb74..39f83faa2 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -19,53 +19,6 @@ #include "sms-cards.h" -struct usb_device_id smsusb_id_table[] = { -#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS - { USB_DEVICE(0x187f, 0x0010), - .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, - { USB_DEVICE(0x187f, 0x0100), - .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, - { USB_DEVICE(0x187f, 0x0200), - .driver_info = SMS1XXX_BOARD_SIANO_NOVA_A }, - { USB_DEVICE(0x187f, 0x0201), - .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B }, - { USB_DEVICE(0x187f, 0x0300), - .driver_info = SMS1XXX_BOARD_SIANO_VEGA }, -#endif - { USB_DEVICE(0x2040, 0x1700), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT }, - { USB_DEVICE(0x2040, 0x1800), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A }, - { USB_DEVICE(0x2040, 0x1801), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B }, - { USB_DEVICE(0x2040, 0x2000), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, - { USB_DEVICE(0x2040, 0x2009), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 }, - { USB_DEVICE(0x2040, 0x200a), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, - { USB_DEVICE(0x2040, 0x2010), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, - { USB_DEVICE(0x2040, 0x2011), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, - { USB_DEVICE(0x2040, 0x2019), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, - { USB_DEVICE(0x2040, 0x5500), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, - { USB_DEVICE(0x2040, 0x5510), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, - { USB_DEVICE(0x2040, 0x5520), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, - { USB_DEVICE(0x2040, 0x5530), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, - { USB_DEVICE(0x2040, 0x5580), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, - { USB_DEVICE(0x2040, 0x5590), - .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, smsusb_id_table); - static struct sms_board sms_boards[] = { [SMS_BOARD_UNKNOWN] = { .name = "Unknown board", diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h index fe292aaea..8f539a2e5 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.h +++ b/linux/drivers/media/dvb/siano/sms-cards.h @@ -54,6 +54,4 @@ int sms_board_led_feedback(struct smscore_device_t *coredev, int led); int sms_board_power(struct smscore_device_t *coredev, int onoff); int sms_board_lna_control(struct smscore_device_t *coredev, int onoff); -extern struct usb_device_id smsusb_id_table[]; - #endif /* __SMS_CARDS_H__ */ diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index 7a04b34b0..19005c26b 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -478,6 +478,53 @@ static int smsusb_resume(struct usb_interface *intf) return 0; } +struct usb_device_id smsusb_id_table[] = { +#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS + { USB_DEVICE(0x187f, 0x0010), + .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, + { USB_DEVICE(0x187f, 0x0100), + .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, + { USB_DEVICE(0x187f, 0x0200), + .driver_info = SMS1XXX_BOARD_SIANO_NOVA_A }, + { USB_DEVICE(0x187f, 0x0201), + .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B }, + { USB_DEVICE(0x187f, 0x0300), + .driver_info = SMS1XXX_BOARD_SIANO_VEGA }, +#endif + { USB_DEVICE(0x2040, 0x1700), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT }, + { USB_DEVICE(0x2040, 0x1800), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A }, + { USB_DEVICE(0x2040, 0x1801), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B }, + { USB_DEVICE(0x2040, 0x2000), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, + { USB_DEVICE(0x2040, 0x2009), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 }, + { USB_DEVICE(0x2040, 0x200a), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, + { USB_DEVICE(0x2040, 0x2010), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, + { USB_DEVICE(0x2040, 0x2011), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, + { USB_DEVICE(0x2040, 0x2019), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, + { USB_DEVICE(0x2040, 0x5500), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5510), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5520), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5530), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5580), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5590), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, smsusb_id_table); + static struct usb_driver smsusb_driver = { .name = "smsusb", .probe = smsusb_probe, -- cgit v1.2.3 From e8a3398295b9a981e3c19553f7908bebe95de079 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 30 Aug 2008 23:44:04 -0400 Subject: import changes from Siano From: Uri Shkolnik Import the following changes from Uri Shkolnik * Two-ways merge with Siano internal repository * Continuing with DVB sub-system separation * kconfig and makefile updates * Code cleanup This is a work-in-progress sync with Siano's internal repository. Some changes had to be altered or dropped in order not to break the build. This breaks normal operation for the current driver, but it is being committed now for tracking purposes. These changes introduce the following checkpatch.pl violations: ERROR: do not use C99 // comments 156: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1373: +//#ifdef DVB_CORE ERROR: do not use C99 // comments 157: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1374: +// smsdvb_unregister(); ERROR: do not use C99 // comments 158: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1375: +//#endif WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 163: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1380: +EXPORT_SYMBOL(smscore_onresponse); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 164: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1381: +EXPORT_SYMBOL(sms_get_board); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 165: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1382: +EXPORT_SYMBOL(sms_debug); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 166: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1383: +EXPORT_SYMBOL(smscore_putbuffer); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 167: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1384: +EXPORT_SYMBOL(smscore_registry_getmode); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 168: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1385: +EXPORT_SYMBOL(smscore_register_device); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 169: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1386: +EXPORT_SYMBOL(smscore_set_board_id); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 170: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1387: +EXPORT_SYMBOL(smscore_start_device); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 171: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1388: +EXPORT_SYMBOL(smsusb_id_table); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 172: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1389: +EXPORT_SYMBOL(smscore_unregister_device); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 173: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1390: +EXPORT_SYMBOL(smscore_getbuffer); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 174: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1391: +EXPORT_SYMBOL(smscore_get_device_mode); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 175: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1392: +EXPORT_SYMBOL(smscore_register_client); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 176: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1393: +EXPORT_SYMBOL(smscore_unregister_hotplug); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 177: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1394: +EXPORT_SYMBOL(smsclient_sendrequest); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 178: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1395: +EXPORT_SYMBOL(smscore_unregister_client); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 179: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1396: +EXPORT_SYMBOL(smscore_get_board_id); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 180: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1397: +EXPORT_SYMBOL(smscore_register_hotplug); WARNING: line over 80 characters 391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398: +extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename); ERROR: "foo* bar" should be "foo *bar" 391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398: +extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename); WARNING: line over 80 characters 392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399: +extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size); ERROR: "foo* bar" should be "foo *bar" 392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399: +extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size); ERROR: space required after that ',' (ctx:VxV) 392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399: +extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size); ^ WARNING: __func__ should be used instead of gcc specific __FUNCTION__ 489: FILE: linux/drivers/media/dvb/siano/smsusb.c:443: + printk(KERN_INFO"%s Entering status %d.\n", __FUNCTION__, msg.event); WARNING: __func__ should be used instead of gcc specific __FUNCTION__ 501: FILE: linux/drivers/media/dvb/siano/smsusb.c:455: + printk(KERN_INFO "%s Entering.\n", __FUNCTION__); ERROR: space prohibited before that '++' (ctx:WxB) 505: FILE: linux/drivers/media/dvb/siano/smsusb.c:459: + for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i ++) ^ WARNING: __func__ should be used instead of gcc specific __FUNCTION__ 517: FILE: linux/drivers/media/dvb/siano/smsusb.c:471: + __FUNCTION__, rc); total: 7 errors, 23 warnings, 524 lines checked Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/Makefile | 4 +- linux/drivers/media/dvb/siano/smscoreapi.c | 121 +++++++++++++++++++++++++---- linux/drivers/media/dvb/siano/smscoreapi.h | 15 ++-- linux/drivers/media/dvb/siano/smsdvb.c | 23 +++--- linux/drivers/media/dvb/siano/smsusb.c | 10 ++- 5 files changed, 134 insertions(+), 39 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/Makefile b/linux/drivers/media/dvb/siano/Makefile index ee0737af9..bcf93f482 100644 --- a/linux/drivers/media/dvb/siano/Makefile +++ b/linux/drivers/media/dvb/siano/Makefile @@ -1,6 +1,8 @@ -sms1xxx-objs := smscoreapi.o smsusb.o smsdvb.o sms-cards.o +sms1xxx-objs := smscoreapi.o sms-cards.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o +obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o +obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsdvb.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index b19dd9c7d..5d56f6295 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -3,7 +3,7 @@ * * This file contains implementation for the interface to sms core component * - * author: Anatoly Greenblat + * author: Uri Shkolnik * * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. * @@ -732,7 +732,7 @@ static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { /*DVBH*/ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, /*TDMB*/ - {"none", "tdmb_nova_12mhz.inp", "none", "none"}, + {"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"}, /*DABIP*/ {"none", "none", "none", "none"}, /*BDA*/ @@ -960,10 +960,6 @@ void smscore_onresponse(struct smscore_device_t *coredev, #endif /* If no client registered for type & id, * check for control client where type is not registered */ -#if 0 - if (!client) - client = smscore_find_client(coredev, 0, phdr->msgDstId); -#endif if (client) rc = client->onresponse_handler(client->context, cb); @@ -1337,12 +1333,67 @@ static int __init smscore_module_init(void) INIT_LIST_HEAD(&g_smscore_registry); kmutex_init(&g_smscore_registrylock); - /* USB Register */ - rc = smsusb_register(); +#if 0 /* def SMS_CHAR_CLIENT */ + /* Char interface Register */ + rc = smschar_register(); + if (rc) { + sms_err("Error registering char device client.\n"); + goto smschar_error; + } +#endif +#if 0 /* def SMS_DVB_CLIENT */ /* DVB Register */ rc = smsdvb_register(); + if (rc) { + sms_err("Error registering DVB client.\n"); + goto smsdvb_error; + } +#endif + +#if 0 /* def SMS_NET_CLIENT */ + /* DVB Register */ + rc = smsnet_register(); + if (rc) { + sms_err("Error registering Network client.\n"); + goto smsnet_error; + } +#endif +#if 0 /* def SMS_USB_BUS_DRV */ + /* USB Register */ + rc = smsusb_register(); + if (rc) { + sms_err("Error registering USB bus driver.\n"); + goto sms_bus_drv_error; + } +#endif + +#if 0 /* def SMS_SPI_BUS_DRV */ + /* USB Register */ + rc = smsspi_register(); + if (rc) { + sms_err("Error registering spi bus driver.\n"); + goto sms_bus_drv_error; + } +#endif + + return rc; +#if 0 +sms_bus_drv_error: +#endif /* 0 */ +#if 0 /* def SMS_NET_CLIENT */ + smsnet_unregister(); +smsnet_error: +#endif +#if 0 /* def SMS_DVB_CLIENT */ + smsdvb_unregister(); +smsdvb_error: +#endif +#if 0 /* def SMS_CHAR_CLIENT */ + smschar_unregister(); +smschar_error: +#endif sms_debug("rc %d", rc); return rc; @@ -1350,6 +1401,30 @@ static int __init smscore_module_init(void) static void __exit smscore_module_exit(void) { +#if 0 /* def SMS_CHAR_CLIENT */ + /* Char interface UnRegister */ + smschar_unregister(); +#endif + +#if 0 /* def SMS_DVB_CLIENT */ + /* DVB UnRegister */ + smsdvb_unregister(); +#endif + +#if 0 /* def SMS_NET_CLIENT */ + /* NET UnRegister */ + smsnet_unregister(); +#endif + +#if 0 /* def SMS_USB_BUS_DRV */ + /* Unregister USB */ + smsusb_unregister(); +#endif + +#if 0 /* def SMS_SPI_BUS_DRV */ + /* Unregister SPI */ + smsspi_unregister(); +#endif kmutex_lock(&g_smscore_deviceslock); while (!list_empty(&g_smscore_notifyees)) { @@ -1373,18 +1448,34 @@ static void __exit smscore_module_exit(void) } kmutex_unlock(&g_smscore_registrylock); - /* DVB UnRegister */ - smsdvb_unregister(); - - /* Unregister USB */ - smsusb_unregister(); +//#ifdef DVB_CORE +// smsdvb_unregister(); +//#endif sms_debug(""); } +EXPORT_SYMBOL(smscore_onresponse); +EXPORT_SYMBOL(sms_get_board); +EXPORT_SYMBOL(sms_debug); +EXPORT_SYMBOL(smscore_putbuffer); +EXPORT_SYMBOL(smscore_registry_getmode); +EXPORT_SYMBOL(smscore_register_device); +EXPORT_SYMBOL(smscore_set_board_id); +EXPORT_SYMBOL(smscore_start_device); +EXPORT_SYMBOL(smscore_unregister_device); +EXPORT_SYMBOL(smscore_getbuffer); +EXPORT_SYMBOL(smscore_get_device_mode); +EXPORT_SYMBOL(smscore_register_client); +EXPORT_SYMBOL(smscore_unregister_hotplug); +EXPORT_SYMBOL(smsclient_sendrequest); +EXPORT_SYMBOL(smscore_unregister_client); +EXPORT_SYMBOL(smscore_get_board_id); +EXPORT_SYMBOL(smscore_register_hotplug); + module_init(smscore_module_init); module_exit(smscore_module_exit); -MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle"); -MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)"); +MODULE_DESCRIPTION("Siano MDTV Core module"); +MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 0469f1bd8..2134a2fb7 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -29,14 +29,14 @@ #include #include #include - +#include #include "compat.h" + #include "dmxdev.h" #include "dvbdev.h" #include "dvb_demux.h" #include "dvb_frontend.h" -#include #define kmutex_init(_p_) mutex_init(_p_) #define kmutex_lock(_p_) mutex_lock(_p_) @@ -551,10 +551,12 @@ extern int smsclient_sendrequest(struct smscore_client_t *client, extern void smscore_onresponse(struct smscore_device_t *coredev, struct smscore_buffer_t *cb); -#if 0 +#if 1 extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev); extern int smscore_map_common_buffer(struct smscore_device_t *coredev, struct vm_area_struct *vma); +extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename); +extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size); #endif extern @@ -571,13 +573,6 @@ int smscore_get_board_id(struct smscore_device_t *core); int smscore_led_state(struct smscore_device_t *core, int led); -/* smsdvb.c */ -int smsdvb_register(void); -void smsdvb_unregister(void); - -/* smsusb.c */ -int smsusb_register(void); -void smsusb_unregister(void); /* ------------------------------------------------------------------------ */ diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index 68f3f31bb..c91f6f242 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -1,7 +1,7 @@ /* * Driver for the Siano SMS1xxx USB dongle * - * author: Anatoly Greenblat + * Author: Uri Shkolni * * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. * @@ -371,7 +371,7 @@ static void smsdvb_release(struct dvb_frontend *fe) static struct dvb_frontend_ops smsdvb_fe_ops = { .info = { - .name = "Siano Mobile Digital SMS1xxx", + .name = "Siano Mobile Digital MDTV Receiver", .type = FE_OFDM, .frequency_min = 44250000, .frequency_max = 867250000, @@ -413,16 +413,10 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, if (!arrival) return 0; - if (smscore_get_device_mode(coredev) != 4) { -#if 1 /* new siano drop (1.2.17) does this -- yuck */ + if (smscore_get_device_mode(coredev) != DEVICE_MODE_DVBT_BDA) { sms_err("SMS Device mode is not set for " "DVB operation."); return 0; -#else - rc = smscore_set_device_mode(coredev, 4); - if (rc < 0) - return rc; -#endif } client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); @@ -521,7 +515,7 @@ adapter_error: return rc; } -int smsdvb_register(void) +int smsdvb_module_init(void) { int rc; @@ -535,7 +529,7 @@ int smsdvb_register(void) return rc; } -void smsdvb_unregister(void) +void smsdvb_module_exit(void) { smscore_unregister_hotplug(smsdvb_hotplug); @@ -547,3 +541,10 @@ void smsdvb_unregister(void) kmutex_unlock(&g_smsdvb_clientslock); } + +module_init(smsdvb_module_init); +module_exit(smsdvb_module_exit); + +MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); +MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index 19005c26b..eb12b08df 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -535,7 +535,7 @@ static struct usb_driver smsusb_driver = { .resume = smsusb_resume, }; -int smsusb_register(void) +int smsusb_module_init(void) { int rc = usb_register(&smsusb_driver); if (rc) @@ -546,10 +546,16 @@ int smsusb_register(void) return rc; } -void smsusb_unregister(void) +void smsusb_module_exit(void) { sms_debug(""); /* Regular USB Cleanup */ usb_deregister(&smsusb_driver); } +module_init(smsusb_module_init); +module_exit(smsusb_module_exit); + +MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle"); +MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 319b736506ba8f695f973876299c72930508f68c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 31 Aug 2008 15:08:15 -0400 Subject: sms1xxx: fix checkpatch.pl violations introduced by previous changeset From: Michael Krufky Fix checkpatch.pl violations introduced by previous changeset: ERROR: do not use C99 // comments 156: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1373: +//#ifdef DVB_CORE ERROR: do not use C99 // comments 157: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1374: +// smsdvb_unregister(); ERROR: do not use C99 // comments 158: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1375: +//#endif WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 163: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1380: +EXPORT_SYMBOL(smscore_onresponse); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 164: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1381: +EXPORT_SYMBOL(sms_get_board); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 165: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1382: +EXPORT_SYMBOL(sms_debug); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 166: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1383: +EXPORT_SYMBOL(smscore_putbuffer); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 167: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1384: +EXPORT_SYMBOL(smscore_registry_getmode); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 168: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1385: +EXPORT_SYMBOL(smscore_register_device); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 169: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1386: +EXPORT_SYMBOL(smscore_set_board_id); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 170: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1387: +EXPORT_SYMBOL(smscore_start_device); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 171: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1388: +EXPORT_SYMBOL(smsusb_id_table); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 172: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1389: +EXPORT_SYMBOL(smscore_unregister_device); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 173: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1390: +EXPORT_SYMBOL(smscore_getbuffer); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 174: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1391: +EXPORT_SYMBOL(smscore_get_device_mode); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 175: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1392: +EXPORT_SYMBOL(smscore_register_client); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 176: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1393: +EXPORT_SYMBOL(smscore_unregister_hotplug); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 177: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1394: +EXPORT_SYMBOL(smsclient_sendrequest); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 178: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1395: +EXPORT_SYMBOL(smscore_unregister_client); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 179: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1396: +EXPORT_SYMBOL(smscore_get_board_id); WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable 180: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1397: +EXPORT_SYMBOL(smscore_register_hotplug); WARNING: line over 80 characters 391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398: +extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename); ERROR: "foo* bar" should be "foo *bar" 391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398: +extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename); WARNING: line over 80 characters 392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399: +extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size); ERROR: "foo* bar" should be "foo *bar" 392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399: +extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size); ERROR: space required after that ',' (ctx:VxV) 392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399: +extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size); ^ WARNING: __func__ should be used instead of gcc specific __FUNCTION__ 489: FILE: linux/drivers/media/dvb/siano/smsusb.c:443: + printk(KERN_INFO"%s Entering status %d.\n", __FUNCTION__, msg.event); WARNING: __func__ should be used instead of gcc specific __FUNCTION__ 501: FILE: linux/drivers/media/dvb/siano/smsusb.c:455: + printk(KERN_INFO "%s Entering.\n", __FUNCTION__); ERROR: space prohibited before that '++' (ctx:WxB) 505: FILE: linux/drivers/media/dvb/siano/smsusb.c:459: + for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i ++) ^ WARNING: __func__ should be used instead of gcc specific __FUNCTION__ 517: FILE: linux/drivers/media/dvb/siano/smsusb.c:471: + __FUNCTION__, rc); Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/sms-cards.c | 5 ++++ linux/drivers/media/dvb/siano/smscoreapi.c | 41 +++++++++++++----------------- linux/drivers/media/dvb/siano/smscoreapi.h | 10 +++++--- linux/drivers/media/dvb/siano/smsdvb.c | 4 +++ linux/drivers/media/dvb/siano/smsusb.c | 13 ++++++---- 5 files changed, 40 insertions(+), 33 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 39f83faa2..4fa86f5b7 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -86,6 +86,7 @@ struct sms_board *sms_get_board(int id) return &sms_boards[id]; } +EXPORT_SYMBOL(sms_get_board); static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) { @@ -138,6 +139,7 @@ int sms_board_setup(struct smscore_device_t *coredev) } return 0; } +EXPORT_SYMBOL(sms_board_setup); int sms_board_power(struct smscore_device_t *coredev, int onoff) { @@ -159,6 +161,7 @@ int sms_board_power(struct smscore_device_t *coredev, int onoff) } return 0; } +EXPORT_SYMBOL(sms_board_power); int sms_board_led_feedback(struct smscore_device_t *coredev, int led) { @@ -181,6 +184,7 @@ int sms_board_led_feedback(struct smscore_device_t *coredev, int led) } return 0; } +EXPORT_SYMBOL(sms_board_led_feedback); int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) { @@ -199,3 +203,4 @@ int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) } return -EINVAL; } +EXPORT_SYMBOL(sms_board_lna_control); diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 5d56f6295..8cb36f540 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -34,8 +34,8 @@ #include "smscoreapi.h" #include "sms-cards.h" -int sms_debug; -module_param_named(debug, sms_debug, int, 0644); +int sms_dbg; +module_param_named(debug, sms_dbg, int, 0644); MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); struct smscore_device_notifyee_t { @@ -105,11 +105,13 @@ int smscore_led_state(struct smscore_device_t *core, int led) core->led_state = led; return core->led_state; } +EXPORT_SYMBOL(smscore_set_board_id); int smscore_get_board_id(struct smscore_device_t *core) { return core->board_id; } +EXPORT_SYMBOL(smscore_get_board_id); struct smscore_registry_entry_t { struct list_head entry; @@ -170,6 +172,7 @@ int smscore_registry_getmode(char *devpath) return default_mode; } +EXPORT_SYMBOL(smscore_registry_getmode); static enum sms_device_type_st smscore_registry_gettype(char *devpath) { @@ -261,6 +264,7 @@ int smscore_register_hotplug(hotplug_t hotplug) return rc; } +EXPORT_SYMBOL(smscore_register_hotplug); /** * unregister a client callback that called when device plugged in/unplugged @@ -289,6 +293,7 @@ void smscore_unregister_hotplug(hotplug_t hotplug) kmutex_unlock(&g_smscore_deviceslock); } +EXPORT_SYMBOL(smscore_unregister_hotplug); static void smscore_notify_clients(struct smscore_device_t *coredev) { @@ -432,6 +437,7 @@ int smscore_register_device(struct smsdevice_params_t *params, return 0; } +EXPORT_SYMBOL(smscore_register_device); /** * sets initial device mode and notifies client hotplugs that device is ready @@ -460,6 +466,7 @@ int smscore_start_device(struct smscore_device_t *coredev) return rc; } +EXPORT_SYMBOL(smscore_start_device); static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, void *buffer, size_t size, @@ -688,6 +695,7 @@ void smscore_unregister_device(struct smscore_device_t *coredev) sms_info("device %p destroyed", coredev); } +EXPORT_SYMBOL(smscore_unregister_device); static int smscore_detect_mode(struct smscore_device_t *coredev) { @@ -879,6 +887,7 @@ int smscore_get_device_mode(struct smscore_device_t *coredev) { return coredev->mode; } +EXPORT_SYMBOL(smscore_get_device_mode); /** * find client by response id & type within the clients list. @@ -1013,6 +1022,7 @@ void smscore_onresponse(struct smscore_device_t *coredev, smscore_putbuffer(coredev, cb); } } +EXPORT_SYMBOL(smscore_onresponse); /** * return pointer to next free buffer descriptor from core pool @@ -1038,6 +1048,7 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) return cb; } +EXPORT_SYMBOL(smscore_getbuffer); /** * return buffer descriptor to a pool @@ -1052,6 +1063,7 @@ void smscore_putbuffer(struct smscore_device_t *coredev, { list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); } +EXPORT_SYMBOL(smscore_putbuffer); static int smscore_validate_client(struct smscore_device_t *coredev, struct smscore_client_t *client, @@ -1131,6 +1143,7 @@ int smscore_register_client(struct smscore_device_t *coredev, return 0; } +EXPORT_SYMBOL(smscore_register_client); /** * frees smsclient object and all subclients associated with it @@ -1161,6 +1174,7 @@ void smscore_unregister_client(struct smscore_client_t *client) spin_unlock_irqrestore(&coredev->clientslock, flags); } +EXPORT_SYMBOL(smscore_unregister_client); /** * verifies that source id is not taken by another client, @@ -1200,6 +1214,7 @@ int smsclient_sendrequest(struct smscore_client_t *client, return coredev->sendrequest_handler(coredev->context, buffer, size); } +EXPORT_SYMBOL(smsclient_sendrequest); #if 0 /** @@ -1448,31 +1463,9 @@ static void __exit smscore_module_exit(void) } kmutex_unlock(&g_smscore_registrylock); -//#ifdef DVB_CORE -// smsdvb_unregister(); -//#endif - sms_debug(""); } -EXPORT_SYMBOL(smscore_onresponse); -EXPORT_SYMBOL(sms_get_board); -EXPORT_SYMBOL(sms_debug); -EXPORT_SYMBOL(smscore_putbuffer); -EXPORT_SYMBOL(smscore_registry_getmode); -EXPORT_SYMBOL(smscore_register_device); -EXPORT_SYMBOL(smscore_set_board_id); -EXPORT_SYMBOL(smscore_start_device); -EXPORT_SYMBOL(smscore_unregister_device); -EXPORT_SYMBOL(smscore_getbuffer); -EXPORT_SYMBOL(smscore_get_device_mode); -EXPORT_SYMBOL(smscore_register_client); -EXPORT_SYMBOL(smscore_unregister_hotplug); -EXPORT_SYMBOL(smsclient_sendrequest); -EXPORT_SYMBOL(smscore_unregister_client); -EXPORT_SYMBOL(smscore_get_board_id); -EXPORT_SYMBOL(smscore_register_hotplug); - module_init(smscore_module_init); module_exit(smscore_module_exit); diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 2134a2fb7..14dcbdd80 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -555,8 +555,10 @@ extern void smscore_onresponse(struct smscore_device_t *coredev, extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev); extern int smscore_map_common_buffer(struct smscore_device_t *coredev, struct vm_area_struct *vma); -extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename); -extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size); +extern int smscore_get_fw_filename(struct smscore_device_t *coredev, + int mode, char *filename); +extern int smscore_send_fw_file(struct smscore_device_t *coredev, + u8 *ufwbuf, int size); #endif extern @@ -576,7 +578,7 @@ int smscore_led_state(struct smscore_device_t *core, int led); /* ------------------------------------------------------------------------ */ -extern int sms_debug; +extern int sms_dbg; #define DBG_INFO 1 #define DBG_ADV 2 @@ -585,7 +587,7 @@ extern int sms_debug; printk(kern "%s: " fmt "\n", __func__, ##arg) #define dprintk(kern, lvl, fmt, arg...) do {\ - if (sms_debug & lvl) \ + if (sms_dbg & lvl) \ sms_printk(kern, fmt, ##arg); } while (0) #define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg) diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index c91f6f242..f7f5569c1 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -50,6 +50,10 @@ struct smsdvb_client_t { static struct list_head g_smsdvb_clients; static struct mutex g_smsdvb_clientslock; +int sms_dbg; +module_param_named(debug, sms_dbg, int, 0644); +MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); + static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index eb12b08df..e5c378e46 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -27,6 +27,10 @@ #include "smscoreapi.h" #include "sms-cards.h" +int sms_dbg; +module_param_named(debug, sms_dbg, int, 0644); +MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); + #define USB1_BUFFER_SIZE 0x1000 #define USB2_BUFFER_SIZE 0x4000 @@ -440,7 +444,7 @@ static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg) { struct smsusb_device_t *dev = (struct smsusb_device_t *)usb_get_intfdata(intf); - printk(KERN_INFO "%s Entering status %d.\n", __func__, msg.event); + printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event); smsusb_stop_streaming(dev); return 0; } @@ -452,7 +456,7 @@ static int smsusb_resume(struct usb_interface *intf) (struct smsusb_device_t *)usb_get_intfdata(intf); struct usb_device *udev = interface_to_usbdev(intf); - printk(KERN_INFO "%s Entering.\n", __func__); + printk(KERN_INFO "%s: Entering.\n", __func__); usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81)); usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02)); @@ -467,9 +471,8 @@ static int smsusb_resume(struct usb_interface *intf) intf->cur_altsetting->desc. bInterfaceNumber, 0); if (rc < 0) { - printk(KERN_INFO - "%s usb_set_interface failed, rc %d\n", - __func__, rc); + printk(KERN_INFO "%s usb_set_interface failed, " + "rc %d\n", __func__, rc); return rc; } } -- cgit v1.2.3 From 7d89270edcc221ddc81a48fb810066488b224b25 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 31 Aug 2008 16:39:58 -0400 Subject: sms1xxx: load smsdvb module automatically based on device id From: Michael Krufky The smsdvb module was separated from the core and usb code. This change loads smsdvb automatically for driver configurations that depend on it. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/sms-cards.c | 17 +++++++++++++++++ linux/drivers/media/dvb/siano/sms-cards.h | 2 ++ linux/drivers/media/dvb/siano/smsusb.c | 1 + 3 files changed, 20 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 4fa86f5b7..44df81a81 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -204,3 +204,20 @@ int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) return -EINVAL; } EXPORT_SYMBOL(sms_board_lna_control); + +int sms_board_load_modules(int id) +{ + switch (id) { + case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT: + case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A: + case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B: + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + request_module("smsdvb"); + break; + default: + /* do nothing */ + break; + } + return 0; +} +EXPORT_SYMBOL(sms_board_load_modules); diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h index 8f539a2e5..64d74c59c 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.h +++ b/linux/drivers/media/dvb/siano/sms-cards.h @@ -54,4 +54,6 @@ int sms_board_led_feedback(struct smscore_device_t *coredev, int led); int sms_board_power(struct smscore_device_t *coredev, int onoff); int sms_board_lna_control(struct smscore_device_t *coredev, int onoff); +extern int sms_board_load_modules(int id); + #endif /* __SMS_CARDS_H__ */ diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index e5c378e46..a2da36122 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -432,6 +432,7 @@ static int smsusb_probe(struct usb_interface *intf, rc = smsusb_init_device(intf, id->driver_info); sms_info("rc %d", rc); + sms_board_load_modules(id->driver_info); return rc; } -- cgit v1.2.3 From 5c190e9dc01651545a2cb6e709953984ebae4be2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 12 Jan 2009 10:17:43 +0100 Subject: tvp514x: make the module aware of rich people From: Sebastian Andrzej Siewior because they might design two of those chips on a single board. You never know. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tvp514x.c | 106 ++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 46 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c index 5f4cbc2b2..f0b2b8ed2 100644 --- a/linux/drivers/media/video/tvp514x.c +++ b/linux/drivers/media/video/tvp514x.c @@ -86,9 +86,12 @@ struct tvp514x_std_info { struct v4l2_standard standard; }; +static struct tvp514x_reg tvp514x_reg_list_default[0x40]; /** - * struct tvp514x_decoded - TVP5146/47 decoder object + * struct tvp514x_decoder - TVP5146/47 decoder object * @v4l2_int_device: Slave handle + * @tvp514x_slave: Slave pointer which is used by @v4l2_int_device + * @tvp514x_regs: copy of hw's regs with preset values. * @pdata: Board specific * @client: I2C client data * @id: Entry from I2C table @@ -103,7 +106,9 @@ struct tvp514x_std_info { * @route: input and output routing at chip level */ struct tvp514x_decoder { - struct v4l2_int_device *v4l2_int_device; + struct v4l2_int_device v4l2_int_device; + struct v4l2_int_slave tvp514x_slave; + struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)]; const struct tvp514x_platform_data *pdata; struct i2c_client *client; @@ -124,7 +129,7 @@ struct tvp514x_decoder { }; /* TVP514x default register values */ -static struct tvp514x_reg tvp514x_reg_list[] = { +static struct tvp514x_reg tvp514x_reg_list_default[] = { {TOK_WRITE, REG_INPUT_SEL, 0x05}, /* Composite selected */ {TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F}, {TOK_WRITE, REG_VIDEO_STD, 0x00}, /* Auto mode */ @@ -422,7 +427,7 @@ static int tvp514x_configure(struct tvp514x_decoder *decoder) /* common register initialization */ err = - tvp514x_write_regs(decoder->client, tvp514x_reg_list); + tvp514x_write_regs(decoder->client, decoder->tvp514x_regs); if (err) return err; @@ -580,7 +585,8 @@ static int ioctl_s_std(struct v4l2_int_device *s, v4l2_std_id *std_id) return err; decoder->current_std = i; - tvp514x_reg_list[REG_VIDEO_STD].val = decoder->std_list[i].video_std; + decoder->tvp514x_regs[REG_VIDEO_STD].val = + decoder->std_list[i].video_std; v4l_dbg(1, debug, decoder->client, "Standard set to: %s", decoder->std_list[i].standard.name); @@ -625,8 +631,8 @@ static int ioctl_s_routing(struct v4l2_int_device *s, if (err) return err; - tvp514x_reg_list[REG_INPUT_SEL].val = input_sel; - tvp514x_reg_list[REG_OUTPUT_FORMATTER1].val = output_sel; + decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel; + decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel; /* Clear status */ msleep(LOCK_RETRY_DELAY); @@ -779,16 +785,16 @@ ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - ctrl->value = tvp514x_reg_list[REG_BRIGHTNESS].val; + ctrl->value = decoder->tvp514x_regs[REG_BRIGHTNESS].val; break; case V4L2_CID_CONTRAST: - ctrl->value = tvp514x_reg_list[REG_CONTRAST].val; + ctrl->value = decoder->tvp514x_regs[REG_CONTRAST].val; break; case V4L2_CID_SATURATION: - ctrl->value = tvp514x_reg_list[REG_SATURATION].val; + ctrl->value = decoder->tvp514x_regs[REG_SATURATION].val; break; case V4L2_CID_HUE: - ctrl->value = tvp514x_reg_list[REG_HUE].val; + ctrl->value = decoder->tvp514x_regs[REG_HUE].val; if (ctrl->value == 0x7F) ctrl->value = 180; else if (ctrl->value == 0x80) @@ -798,7 +804,7 @@ ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) break; case V4L2_CID_AUTOGAIN: - ctrl->value = tvp514x_reg_list[REG_AFE_GAIN_CTRL].val; + ctrl->value = decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val; if ((ctrl->value & 0x3) == 3) ctrl->value = 1; else @@ -848,7 +854,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_BRIGHTNESS].val = value; + decoder->tvp514x_regs[REG_BRIGHTNESS].val = value; break; case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 255) { @@ -861,7 +867,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_CONTRAST].val = value; + decoder->tvp514x_regs[REG_CONTRAST].val = value; break; case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 255) { @@ -874,7 +880,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_SATURATION].val = value; + decoder->tvp514x_regs[REG_SATURATION].val = value; break; case V4L2_CID_HUE: if (value == 180) @@ -893,7 +899,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_HUE].val = value; + decoder->tvp514x_regs[REG_HUE].val = value; break; case V4L2_CID_AUTOGAIN: if (value == 1) @@ -910,7 +916,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_AFE_GAIN_CTRL].val = value; + decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value; break; default: v4l_err(decoder->client, @@ -1275,7 +1281,7 @@ static int ioctl_init(struct v4l2_int_device *s) struct tvp514x_decoder *decoder = s->priv; /* Set default standard to auto */ - tvp514x_reg_list[REG_VIDEO_STD].val = + decoder->tvp514x_regs[REG_VIDEO_STD].val = VIDEO_STD_AUTO_SWITCH_BIT; return tvp514x_configure(decoder); @@ -1344,11 +1350,6 @@ static struct v4l2_int_ioctl_desc tvp514x_ioctl_desc[] = { (v4l2_int_ioctl_func *) ioctl_s_routing}, }; -static struct v4l2_int_slave tvp514x_slave = { - .ioctls = tvp514x_ioctl_desc, - .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc), -}; - static struct tvp514x_decoder tvp514x_dev = { .state = STATE_NOT_DETECTED, @@ -1369,17 +1370,15 @@ static struct tvp514x_decoder tvp514x_dev = { .current_std = STD_NTSC_MJ, .std_list = tvp514x_std_list, .num_stds = ARRAY_SIZE(tvp514x_std_list), - -}; - -static struct v4l2_int_device tvp514x_int_device = { - .module = THIS_MODULE, - .name = TVP514X_MODULE_NAME, - .priv = &tvp514x_dev, - .type = v4l2_int_type_slave, - .u = { - .slave = &tvp514x_slave, - }, + .v4l2_int_device = { + .module = THIS_MODULE, + .name = TVP514X_MODULE_NAME, + .type = v4l2_int_type_slave, + }, + .tvp514x_slave = { + .ioctls = tvp514x_ioctl_desc, + .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc), + }, }; /** @@ -1392,26 +1391,37 @@ static struct v4l2_int_device tvp514x_int_device = { static int tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct tvp514x_decoder *decoder = &tvp514x_dev; + struct tvp514x_decoder *decoder; int err; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - decoder->pdata = client->dev.platform_data; - if (!decoder->pdata) { + decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); + if (!decoder) + return -ENOMEM; + + if (!client->dev.platform_data) { v4l_err(client, "No platform data!!\n"); - return -ENODEV; + err = -ENODEV; + goto out_free; } + + *decoder = tvp514x_dev; + decoder->v4l2_int_device.priv = decoder; + decoder->pdata = client->dev.platform_data; + decoder->v4l2_int_device.u.slave = &decoder->tvp514x_slave; + memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, + sizeof(tvp514x_reg_list_default)); /* * Fetch platform specific data, and configure the * tvp514x_reg_list[] accordingly. Since this is one * time configuration, no need to preserve. */ - tvp514x_reg_list[REG_OUTPUT_FORMATTER2].val |= + decoder->tvp514x_regs[REG_OUTPUT_FORMATTER2].val |= (decoder->pdata->clk_polarity << 1); - tvp514x_reg_list[REG_SYNC_CONTROL].val |= + decoder->tvp514x_regs[REG_SYNC_CONTROL].val |= ((decoder->pdata->hs_polarity << 2) | (decoder->pdata->vs_polarity << 3)); /* @@ -1419,23 +1429,27 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) */ decoder->id = (struct i2c_device_id *)id; /* Attach to Master */ - strcpy(tvp514x_int_device.u.slave->attach_to, decoder->pdata->master); - decoder->v4l2_int_device = &tvp514x_int_device; + strcpy(decoder->v4l2_int_device.u.slave->attach_to, + decoder->pdata->master); decoder->client = client; i2c_set_clientdata(client, decoder); /* Register with V4L2 layer as slave device */ - err = v4l2_int_device_register(decoder->v4l2_int_device); + err = v4l2_int_device_register(&decoder->v4l2_int_device); if (err) { i2c_set_clientdata(client, NULL); v4l_err(client, "Unable to register to v4l2. Err[%d]\n", err); + goto out_free; } else v4l_info(client, "Registered to v4l2 master %s!!\n", decoder->pdata->master); - return 0; + +out_free: + kfree(decoder); + return err; } /** @@ -1452,9 +1466,9 @@ static int __exit tvp514x_remove(struct i2c_client *client) if (!client->adapter) return -ENODEV; /* our client isn't attached */ - v4l2_int_device_unregister(decoder->v4l2_int_device); + v4l2_int_device_unregister(&decoder->v4l2_int_device); i2c_set_clientdata(client, NULL); - + kfree(decoder); return 0; } /* -- cgit v1.2.3 From fb3a9246d433dda2f7ace056abb2574ed3a9da42 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 27 Jan 2009 06:02:41 +0000 Subject: tw9910: color format check is added on set_fmt From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tw9910.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index c670b23a1..4593cdea7 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -645,6 +645,19 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); int ret = -EINVAL; u8 val; + int i; + + /* + * check color format + */ + for (i = 0 ; i < ARRAY_SIZE(tw9910_color_fmt) ; i++) { + if (pixfmt == tw9910_color_fmt[i].fourcc) { + ret = 0; + break; + } + } + if (ret < 0) + goto tw9910_set_fmt_error; /* * select suitable norm -- cgit v1.2.3 From 13e2e59a82953d5b837a02c7115ae6fad1c0f1d4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 23:58:33 +0100 Subject: ivtv: fix decoder crash regression From: Hans Verkuil The video_ioctl2 conversion of ivtv in kernel 2.6.27 introduced a bug causing decoder commands to crash. The decoder commands should have been handled from the video_ioctl2 default handler, ensuring correct mapping of the argument between user and kernel space. Unfortunately they ended up before the video_ioctl2 call, causing random crashes. Thanks to hannes@linus.priv.at for testing and helping me track down the cause! Priority: high Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index aa55a3cc4..d7a708ad3 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1752,6 +1752,18 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg) break; } + case IVTV_IOC_DMA_FRAME: + case VIDEO_GET_PTS: + case VIDEO_GET_FRAME_COUNT: + case VIDEO_GET_EVENT: + case VIDEO_PLAY: + case VIDEO_STOP: + case VIDEO_FREEZE: + case VIDEO_CONTINUE: + case VIDEO_COMMAND: + case VIDEO_TRY_COMMAND: + return ivtv_decoder_ioctls(file, cmd, (void *)arg); + default: return -EINVAL; } @@ -1794,18 +1806,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); return 0; - case IVTV_IOC_DMA_FRAME: - case VIDEO_GET_PTS: - case VIDEO_GET_FRAME_COUNT: - case VIDEO_GET_EVENT: - case VIDEO_PLAY: - case VIDEO_STOP: - case VIDEO_FREEZE: - case VIDEO_CONTINUE: - case VIDEO_COMMAND: - case VIDEO_TRY_COMMAND: - return ivtv_decoder_ioctls(filp, cmd, (void *)arg); - default: break; } -- cgit v1.2.3 From 337e145d4f292cbeeb8dd95c70ecef641230a657 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 16 Feb 2009 08:25:32 +0100 Subject: ivtv: fix regression in get sliced vbi format From: Hans Verkuil The new v4l2_subdev_call used s_fmt instead of g_fmt. Priority: high Signed-off-by: Hans Verkuil Thanks-to: Andy Walls --- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index d7a708ad3..9a0424298 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -391,7 +391,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo return 0; } - v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); + v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt); vbifmt->service_set = ivtv_get_service_set(vbifmt); return 0; } -- cgit v1.2.3 From fa940b36a68186b4e5b77a5afb929f68603b52bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 21:06:49 +0000 Subject: V4L: Storage class should be before const qualifier From: Tobias Klauser The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser CC: Jean-Francois Moine CC: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/t613.c | 2 +- linux/drivers/media/video/tcm825x.c | 22 +++++++++++----------- linux/drivers/media/video/tcm825x.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index adec0767c..c04836ed2 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -272,7 +272,7 @@ struct additional_sensor_data { const u8 stream[4]; }; -const static struct additional_sensor_data sensor_data[] = { +static const struct additional_sensor_data sensor_data[] = { { /* OM6802 */ .data1 = {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, diff --git a/linux/drivers/media/video/tcm825x.c b/linux/drivers/media/video/tcm825x.c index 2f823f27a..559ade821 100644 --- a/linux/drivers/media/video/tcm825x.c +++ b/linux/drivers/media/video/tcm825x.c @@ -50,7 +50,7 @@ struct tcm825x_sensor { }; /* list of image formats supported by TCM825X sensor */ -const static struct v4l2_fmtdesc tcm825x_formats[] = { +static const struct v4l2_fmtdesc tcm825x_formats[] = { { .description = "YUYV (YUV 4:2:2), packed", .pixelformat = V4L2_PIX_FMT_UYVY, @@ -76,15 +76,15 @@ const static struct v4l2_fmtdesc tcm825x_formats[] = { * TCM825X register configuration for all combinations of pixel format and * image size */ -const static struct tcm825x_reg subqcif = { 0x20, TCM825X_PICSIZ }; -const static struct tcm825x_reg qcif = { 0x18, TCM825X_PICSIZ }; -const static struct tcm825x_reg cif = { 0x14, TCM825X_PICSIZ }; -const static struct tcm825x_reg qqvga = { 0x0c, TCM825X_PICSIZ }; -const static struct tcm825x_reg qvga = { 0x04, TCM825X_PICSIZ }; -const static struct tcm825x_reg vga = { 0x00, TCM825X_PICSIZ }; +static const struct tcm825x_reg subqcif = { 0x20, TCM825X_PICSIZ }; +static const struct tcm825x_reg qcif = { 0x18, TCM825X_PICSIZ }; +static const struct tcm825x_reg cif = { 0x14, TCM825X_PICSIZ }; +static const struct tcm825x_reg qqvga = { 0x0c, TCM825X_PICSIZ }; +static const struct tcm825x_reg qvga = { 0x04, TCM825X_PICSIZ }; +static const struct tcm825x_reg vga = { 0x00, TCM825X_PICSIZ }; -const static struct tcm825x_reg yuv422 = { 0x00, TCM825X_PICFMT }; -const static struct tcm825x_reg rgb565 = { 0x02, TCM825X_PICFMT }; +static const struct tcm825x_reg yuv422 = { 0x00, TCM825X_PICFMT }; +static const struct tcm825x_reg rgb565 = { 0x02, TCM825X_PICFMT }; /* Our own specific controls */ #define V4L2_CID_ALC V4L2_CID_PRIVATE_BASE @@ -248,10 +248,10 @@ static struct vcontrol { }; -const static struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] = +static const struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] = { &subqcif, &qqvga, &qcif, &qvga, &cif, &vga }; -const static struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] = +static const struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] = { &yuv422, &rgb565 }; /* diff --git a/linux/drivers/media/video/tcm825x.h b/linux/drivers/media/video/tcm825x.h index 770ebacfa..5b7e69682 100644 --- a/linux/drivers/media/video/tcm825x.h +++ b/linux/drivers/media/video/tcm825x.h @@ -188,7 +188,7 @@ struct tcm825x_platform_data { /* Array of image sizes supported by TCM825X. These must be ordered from * smallest image size to largest. */ -const static struct capture_size tcm825x_sizes[] = { +static const struct capture_size tcm825x_sizes[] = { { 128, 96 }, /* subQCIF */ { 160, 120 }, /* QQVGA */ { 176, 144 }, /* QCIF */ -- cgit v1.2.3 From ae420af84b9a311c94b8c41557e700a13fe2f520 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 21:57:06 +0000 Subject: tvp514x: try_count reaches 0, not -1 From: Roel Kluin with while (try_count-- > 0) { ... } try_count reaches 0, not -1. Signed-off-by: Roel Kluin CC: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tvp514x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c index 8e23aa53c..5f4cbc2b2 100644 --- a/linux/drivers/media/video/tvp514x.c +++ b/linux/drivers/media/video/tvp514x.c @@ -686,7 +686,7 @@ static int ioctl_s_routing(struct v4l2_int_device *s, break; /* Input detected */ } - if ((current_std == STD_INVALID) || (try_count < 0)) + if ((current_std == STD_INVALID) || (try_count <= 0)) return -EINVAL; decoder->current_std = current_std; -- cgit v1.2.3 From de8d080a697cf4a8c8c997f7f3b76ea1f49a51bd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Feb 2009 09:34:11 +0000 Subject: V4L/DVB: calibration still successful at 10 From: Roel Kluin With while (i++ < 10) { ... } i can reach 11, so callibration still succeeds at i == 10. Signed-off-by: Roel Kluin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/mt2060.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/mt2060.c b/linux/drivers/media/common/tuners/mt2060.c index d1962bb24..1f1fe90cb 100644 --- a/linux/drivers/media/common/tuners/mt2060.c +++ b/linux/drivers/media/common/tuners/mt2060.c @@ -285,7 +285,7 @@ static void mt2060_calibrate(struct mt2060_priv *priv) while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0) msleep(20); - if (i < 10) { + if (i <= 10) { mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :) dprintk("calibration was successful: %d", (int)priv->fmfreq); } else -- cgit v1.2.3 From e07511c36db32bec6bd0fde4e996001b6e5709e0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 12 Feb 2009 18:19:24 +0000 Subject: zoran: fix printk format From: Randy Dunlap Fix printk format warning: drivers/media/video/zoran/zoran_driver.c:345: warning: format '%lx' expects type 'long unsigned int', but argument 5 has type 'phys_addr_t' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zoran/zoran_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 2609f54d7..798745c0a 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -356,9 +356,9 @@ v4l_fbuffer_alloc (struct file *file) SetPageReserved(MAP_NR(mem + off)); dprintk(4, KERN_INFO - "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", + "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%llx)\n", ZR_DEVNAME(zr), i, (unsigned long) mem, - virt_to_bus(mem)); + (unsigned long long)virt_to_bus(mem)); } else { #if defined(CONFIG_BIGPHYS_AREA) /* Use bigphysarea_alloc_pages */ -- cgit v1.2.3 From d5e10736ed6dd53b02e973042f407a3316c28533 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 12 Feb 2009 06:43:11 +0000 Subject: Added support for AVerMedia Cardbus Hybrid remote control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Oldřich Jedlička Added support for I2C device at address 0x40 and subaddress 0x0d/0x0b that provides remote control key reading support for AVerMedia Cardbus Hybrid card, possibly for other AVerMedia Cardbus cards. The I2C address 0x40 doesn't like the SAA7134's 0xfd quirk, so it was disabled. Signed-off-by: Oldřich Jedlička [mchehab@redhat.com: CodingStyle fixes] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 59 +++++++++++++++++++++ linux/drivers/media/video/ir-kbd-i2c.c | 64 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-cards.c | 5 ++ linux/drivers/media/video/saa7134/saa7134-i2c.c | 2 +- 4 files changed, 129 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 03fabc86c..827e65582 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -154,6 +154,65 @@ IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a); +/* Oldrich Jedlicka */ +IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = { + [0x00] = KEY_POWER, + [0x01] = KEY_TUNER, /* TV/FM */ + [0x03] = KEY_TEXT, /* Teletext */ + [0x04] = KEY_EPG, + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x08] = KEY_AUDIO, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0c] = KEY_ZOOM, /* Full screen */ + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + [0x10] = KEY_PAGEUP, /* 16-CH PREV */ + [0x11] = KEY_0, + [0x12] = KEY_INFO, + [0x13] = KEY_AGAIN, /* CH RTN - channel return */ + [0x14] = KEY_MUTE, + [0x15] = KEY_EDIT, /* Autoscan */ + [0x17] = KEY_SAVE, /* Screenshot */ + [0x18] = KEY_PLAYPAUSE, + [0x19] = KEY_RECORD, + [0x1a] = KEY_PLAY, + [0x1b] = KEY_STOP, + [0x1c] = KEY_FASTFORWARD, + [0x1d] = KEY_REWIND, + [0x1e] = KEY_VOLUMEDOWN, + [0x1f] = KEY_VOLUMEUP, + [0x22] = KEY_SLEEP, /* Sleep */ + [0x23] = KEY_ZOOM, /* Aspect */ + [0x26] = KEY_SCREEN, /* Pos */ + [0x27] = KEY_ANGLE, /* Size */ + [0x28] = KEY_SELECT, /* Select */ + [0x29] = KEY_BLUE, /* Blue/Picture */ + [0x2a] = KEY_BACKSPACE, /* Back */ + [0x2b] = KEY_MEDIA, /* PIP (Picture-in-picture) */ + [0x2c] = KEY_DOWN, + [0x2e] = KEY_DOT, + [0x2f] = KEY_TV, /* Live TV */ + [0x32] = KEY_LEFT, + [0x33] = KEY_CLEAR, /* Clear */ + [0x35] = KEY_RED, /* Red/TV */ + [0x36] = KEY_UP, + [0x37] = KEY_HOME, /* Home */ + [0x39] = KEY_GREEN, /* Green/Video */ + [0x3d] = KEY_YELLOW, /* Yellow/Music */ + [0x3e] = KEY_OK, /* Ok */ + [0x3f] = KEY_RIGHT, + [0x40] = KEY_NEXT, /* Next */ + [0x41] = KEY_PREVIOUS, /* Previous */ + [0x42] = KEY_CHANNELDOWN, /* Channel down */ + [0x43] = KEY_CHANNELUP /* Channel up */ +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus); + /* Attila Kondoros */ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index a67bed7d7..a99aea49a 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -16,6 +16,8 @@ * Henry Wong * Mark Schultz * Brian Rogers + * modified for AVerMedia Cardbus by + * Oldrich Jedlicka * * 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 @@ -217,6 +219,46 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } +static int get_key_avermedia_cardbus(struct IR_i2c *ir, + u32 *ir_key, u32 *ir_raw) +{ + unsigned char subaddr, key, keygroup; + struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0, + .buf = &subaddr, .len = 1}, + { .addr = ir->c.addr, .flags = I2C_M_RD, + .buf = &key, .len = 1} }; + subaddr = 0x0d; + if (2 != i2c_transfer(ir->c.adapter, msg, 2)) { + dprintk(1, "read error\n"); + return -EIO; + } + + if (key == 0xff) + return 0; + + subaddr = 0x0b; + msg[1].buf = &keygroup; + if (2 != i2c_transfer(ir->c.adapter, msg, 2)) { + dprintk(1, "read error\n"); + return -EIO; + } + + if (keygroup == 0xff) + return 0; + + dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup); + if (keygroup < 2 || keygroup > 3) { + /* Only a warning */ + dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n", + keygroup, key); + } + key |= (keygroup & 1) << 6; + + *ir_key = key; + *ir_raw = key; + return 1; +} + /* ----------------------------------------------------------------------- */ static void ir_key_poll(struct IR_i2c *ir) @@ -369,6 +411,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_type = IR_TYPE_OTHER; } break; + case 0x40: + name = "AVerMedia Cardbus remote"; + ir->get_key = get_key_avermedia_cardbus; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_avermedia_cardbus; + break; default: /* shouldn't happen */ printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr); @@ -537,6 +585,22 @@ static int ir_probe(struct i2c_adapter *adap) ir_attach(adap, msg.addr, 0, 0); } + /* Special case for AVerMedia Cardbus remote */ + if (adap->id == I2C_HW_SAA7134) { + unsigned char subaddr, data; + struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0, + .buf = &subaddr, .len = 1}, + { .addr = 0x40, .flags = I2C_M_RD, + .buf = &data, .len = 1} }; + subaddr = 0x0d; + rc = i2c_transfer(adap, msg, 2); + dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n", + msg[0].addr, subaddr, adap->name, + (2 == rc) ? "yes" : "no"); + if (2 == rc) + ir_attach(adap, msg[0].addr, 0, 0); + } + return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index e565d437b..9db045cf5 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -6120,6 +6120,11 @@ int saa7134_board_init1(struct saa7134_dev *dev) msleep(10); break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + saa7134_set_gpio(dev, 23, 0); + msleep(10); + saa7134_set_gpio(dev, 23, 1); + dev->has_remote = SAA7134_REMOTE_I2C; + break; case SAA7134_BOARD_AVERMEDIA_M103: saa7134_set_gpio(dev, 23, 0); msleep(10); diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index 4b4d5ef76..b77ccb5a0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -260,7 +260,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, addr = msgs[i].addr << 1; if (msgs[i].flags & I2C_M_RD) addr |= 1; - if (i > 0 && msgs[i].flags & I2C_M_RD) { + if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) { /* workaround for a saa7134 i2c bug * needed to talk to the mt352 demux * thanks to pinnacle for the hint */ -- cgit v1.2.3 From e63d9cf5d9e5f269f241490e6e190e8f4d92a5d0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 1 Feb 2009 22:31:54 +0000 Subject: DAB: fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Márton Németh Fix typo in "DAB adapters" section in Kconfig. Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig index 93ea201f4..223c36ede 100644 --- a/linux/drivers/media/Kconfig +++ b/linux/drivers/media/Kconfig @@ -117,7 +117,7 @@ source "drivers/media/dvb/Kconfig" config DAB boolean "DAB adapters" ---help--- - Allow selecting support for for Digital Audio Broadcasting (DAB) + Allow selecting support for Digital Audio Broadcasting (DAB) Receiver adapters. if DAB -- cgit v1.2.3 From 4b7ea770410dae8b9ca79623e4e36e94dfa86fd4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Feb 2009 11:43:50 +0100 Subject: gspca - vc032x: Remove the vc0321 reset. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 1832d241f..72cbf56c9 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -2098,6 +2098,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, /*not reached*/ } +#if 0 static void vc0321_reset(struct gspca_dev *gspca_dev) { reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d); @@ -2106,6 +2107,7 @@ static void vc0321_reset(struct gspca_dev *gspca_dev) reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb003); msleep(100); } +#endif /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, @@ -2118,8 +2120,9 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; sd->bridge = id->driver_info; - +#if 0 vc0321_reset(gspca_dev); +#endif sensor = vc032x_probe_sensor(gspca_dev); switch (sensor) { case -1: -- cgit v1.2.3 From c1d676109e87244212120f7ba938d67c3d0571a0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Feb 2009 20:25:38 +0100 Subject: gspca - some drivers: Fix compilation warnings. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/mr97310a.c | 2 +- linux/drivers/media/video/gspca/sonixj.c | 2 +- linux/drivers/media/video/gspca/spca505.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 3a5ddff8f..5ec5ce6e3 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -73,7 +73,7 @@ static int reg_w(struct gspca_dev *gspca_dev, int len) rc = usb_bulk_msg(gspca_dev->dev, usb_sndbulkpipe(gspca_dev->dev, 4), - gspca_dev->usb_buf, len, 0, 500); + gspca_dev->usb_buf, len, NULL, 500); if (rc < 0) PDEBUG(D_ERR, "reg write [%02x] error %d", gspca_dev->usb_buf[0], rc); diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 0aa4649bd..3be96d9f4 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1031,7 +1031,7 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i, j; - u16 val; + u16 val = 0; static const u8 probe_tb[][4][8] = { { /* mi0360 */ {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, diff --git a/linux/drivers/media/video/gspca/spca505.c b/linux/drivers/media/video/gspca/spca505.c index 4fc54d8b8..2acec58b1 100644 --- a/linux/drivers/media/video/gspca/spca505.c +++ b/linux/drivers/media/video/gspca/spca505.c @@ -426,8 +426,8 @@ static const u8 spca505b_open_data_ccd[][3] = { {0x05, 0x00, 0x11}, {0x05, 0x00, 0x12}, {0x05, 0x6f, 0x00}, - {0x05, (u8) (initial_brightness >> 6), 0x00}, - {0x05, (u8) (initial_brightness << 2), 0x01}, + {0x05, initial_brightness >> 6, 0x00}, + {0x05, (initial_brightness << 2) & 0xff, 0x01}, {0x05, 0x00, 0x02}, {0x05, 0x01, 0x03}, {0x05, 0x00, 0x04}, @@ -560,8 +560,8 @@ static const u8 spca505b_open_data_ccd[][3] = { {0x06, 0x5f, 0x1f}, {0x06, 0x32, 0x20}, - {0x05, (u8) (initial_brightness >> 6), 0x00}, - {0x05, (u8) (initial_brightness << 2), 0x01}, + {0x05, initial_brightness >> 6, 0x00}, + {0x05, (initial_brightness << 2) & 0xff, 0x01}, {0x05, 0x06, 0xc1}, {0x05, 0x58, 0xc2}, {0x05, 0x00, 0xca}, -- cgit v1.2.3 From e086109f0cad2b76f5a32cf18db838e2026712bb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 4 Feb 2009 19:33:21 +0100 Subject: gspca - main: Destroy the URBs at disconnection time. From: Adam Baker If a device using the gspca framework is unplugged while it is still streaming then the call that is used to free the URBs that have been allocated occurs after the pointer it uses becomes invalid at the end of gspca_disconnect. Make another cleanup call in gspca_disconnect while the pointer is still valid (multiple calls are OK as destroy_urbs checks for pointers already being NULL. Priority: high Signed-off-by: Adam Baker Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index cac937040..64842682e 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -434,6 +434,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) if (urb == NULL) break; + BUG_ON(!gspca_dev->dev); gspca_dev->urb[i] = NULL; if (!gspca_dev->present) usb_kill_urb(urb); @@ -1953,8 +1954,12 @@ void gspca_disconnect(struct usb_interface *intf) { struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + mutex_lock(&gspca_dev->usb_lock); gspca_dev->present = 0; + mutex_unlock(&gspca_dev->usb_lock); + destroy_urbs(gspca_dev); + gspca_dev->dev = NULL; usb_set_intfdata(intf, NULL); /* release the device */ -- cgit v1.2.3 From 8d372d7b7fad4952e30da202fa0be5905382a8fd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 5 Feb 2009 19:04:33 +0100 Subject: gspca - sonixj: No vertical flip control for mt9v111. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 3be96d9f4..6c5ec09a5 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -235,9 +235,9 @@ static __u32 ctrl_dis[] = { (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_MO4000 2 */ #if 1 - 0, + (1 << VFLIP_IDX), #else - (1 << AUTOGAIN_IDX), + (1 << AUTOGAIN_IDX) | (1 << VFLIP_IDX), #endif /* SENSOR_MT9V111 3 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), -- cgit v1.2.3 From 1aa4c1b8e3ab0204e2985d4a13d81379b5fb7b02 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 5 Feb 2009 19:12:24 +0100 Subject: gspca - sonixj: Add autogain for ov7630/48 and vflip for ov7648. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 43 ++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 6c5ec09a5..5cdb643b8 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -45,7 +45,7 @@ struct sd { u8 blue; u8 red; u8 gamma; - u8 vflip; /* ov7630 only */ + u8 vflip; /* ov7630/ov7648 only */ u8 infrared; /* mt9v111 only */ s8 ag_cnt; @@ -192,7 +192,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, -/* ov7630 only */ +/* ov7630/ov7648 only */ #define VFLIP_IDX 6 { { @@ -202,7 +202,7 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, -#define VFLIP_DEF 1 +#define VFLIP_DEF 0 /* vflip def = 1 for ov7630 */ .default_value = VFLIP_DEF, }, .set = sd_setvflip, @@ -244,7 +244,7 @@ static __u32 ctrl_dis[] = { /* SENSOR_OM6802 4 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX), /* SENSOR_OV7630 5 */ - (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + (1 << INFRARED_IDX), /* SENSOR_OV7648 6 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OV7660 7 */ @@ -677,7 +677,8 @@ static const u8 ov7648_sensor_init[][8] = { {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, /*...*/ /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ -/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */ +/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN + * set by setvflip */ {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, /* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */ @@ -1319,7 +1320,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->gamma = GAMMA_DEF; sd->autogain = AUTOGAIN_DEF; sd->ag_cnt = -1; - sd->vflip = VFLIP_DEF; + if (sd->sensor != SENSOR_OV7630) + sd->vflip = 0; + else + sd->vflip = 1; sd->infrared = INFRARED_DEF; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; @@ -1589,16 +1593,39 @@ static void setautogain(struct gspca_dev *gspca_dev) if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) return; + switch (sd->sensor) { + case SENSOR_OV7630: + case SENSOR_OV7648: { + u8 comb; + + if (sd->sensor == SENSOR_OV7630) + comb = 0xc0; + else + comb = 0xa0; + if (sd->autogain) + comb |= 0x02; + i2c_w1(&sd->gspca_dev, 0x13, comb); + return; + } + } if (sd->autogain) sd->ag_cnt = AG_CNT_START; else sd->ag_cnt = -1; } +/* ov7630/ov7648 only */ static void setvflip(struct sd *sd) { - i2c_w1(&sd->gspca_dev, 0x75, /* COMN */ - sd->vflip ? 0x82 : 0x02); + u8 comn; + + if (sd->sensor == SENSOR_OV7630) + comn = 0x02; + else + comn = 0x06; + if (sd->vflip) + comn |= 0x80; + i2c_w1(&sd->gspca_dev, 0x75, comn); } static void setinfrared(struct sd *sd) -- cgit v1.2.3 From 891ac17d7e12b75ddf21bea407b502569f94bb3e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 6 Feb 2009 17:45:23 +0100 Subject: gspca - t613: Bad sensor name in kernel trace when 'other' sensor. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index adec0767c..1b0fc86c4 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -685,7 +685,7 @@ static int sd_init(struct gspca_dev *gspca_dev) sd->sensor = SENSOR_TAS5130A; break; case 0x0803: - PDEBUG(D_CONF, "sensor om6802"); + PDEBUG(D_CONF, "sensor 'other'"); sd->sensor = SENSOR_OTHER; break; case 0x0807: -- cgit v1.2.3 From a50f33bc015e6def039a24ead62b4e32d76d44e6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 6 Feb 2009 18:11:58 +0100 Subject: gspca - t613: Bad debug level when displaying the sensor type. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/t613.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index 1b0fc86c4..4891592ea 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -681,19 +681,19 @@ static int sd_init(struct gspca_dev *gspca_dev) | reg_r(gspca_dev, 0x07); switch (sensor_id) { case 0x0801: - PDEBUG(D_CONF, "sensor tas5130a"); + PDEBUG(D_PROBE, "sensor tas5130a"); sd->sensor = SENSOR_TAS5130A; break; case 0x0803: - PDEBUG(D_CONF, "sensor 'other'"); + PDEBUG(D_PROBE, "sensor 'other'"); sd->sensor = SENSOR_OTHER; break; case 0x0807: - PDEBUG(D_CONF, "sensor om6802"); + PDEBUG(D_PROBE, "sensor om6802"); sd->sensor = SENSOR_OM6802; break; default: - PDEBUG(D_CONF, "unknown sensor %04x", sensor_id); + PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id); return -EINVAL; } -- cgit v1.2.3 From 9e943ca0c659d66896f55dcfa1280f1d22556e78 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 6 Feb 2009 19:12:46 +0100 Subject: gspca - sq905: New subdriver. From: Adam Baker Add initial support for cameras based on the SQ Technologies SQ-905 chipset (USB ID 2770:9120) to V4L2 using the gspca infrastructure. Currently only supports one resolution and doesn't attempt to inform libv4l what image flipping options are needed. Priority: normal Signed-off-by: Adam Baker Signed-off-by: Theodore Kilgore Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/Kconfig | 9 + linux/drivers/media/video/gspca/Makefile | 2 + linux/drivers/media/video/gspca/sq905.c | 438 +++++++++++++++++++++++++++++++ 3 files changed, 449 insertions(+) create mode 100644 linux/drivers/media/video/gspca/sq905.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index 11c5d2fc2..a0f05ef5c 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -176,6 +176,15 @@ config USB_GSPCA_SPCA561 To compile this driver as a module, choose M here: the module will be called gspca_spca561. +config USB_GSPCA_SQ905 + tristate "SQ Technologies SQ905 based USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SQ905 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_sq905. + config USB_GSPCA_STK014 tristate "Syntek DV4000 (STK014) USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile index b3cbcc176..b6ec61185 100644 --- a/linux/drivers/media/video/gspca/Makefile +++ b/linux/drivers/media/video/gspca/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o +obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o @@ -41,6 +42,7 @@ gspca_spca505-objs := spca505.o gspca_spca506-objs := spca506.o gspca_spca508-objs := spca508.o gspca_spca561-objs := spca561.o +gspca_sq905-objs := sq905.o gspca_stk014-objs := stk014.o gspca_sunplus-objs := sunplus.o gspca_t613-objs := t613.o diff --git a/linux/drivers/media/video/gspca/sq905.c b/linux/drivers/media/video/gspca/sq905.c new file mode 100644 index 000000000..dafaed69e --- /dev/null +++ b/linux/drivers/media/video/gspca/sq905.c @@ -0,0 +1,438 @@ +/* + * SQ905 subdriver + * + * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore + * + * 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 + * 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 + */ + +/* + * History and Acknowledgments + * + * The original Linux driver for SQ905 based cameras was written by + * Marcell Lengyel and furter developed by many other contributers + * and is available from http://sourceforge.net/projects/sqcam/ + * + * This driver takes advantage of the reverse engineering work done for + * that driver and for libgphoto2 but shares no code with them. + * + * This driver has used as a base the finepix driver and other gspca + * based drivers and may still contain code fragments taken from those + * drivers. + */ + +#define MODULE_NAME "sq905" + +#include +#include "gspca.h" + +MODULE_AUTHOR("Adam Baker , " + "Theodore Kilgore "); +MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* Default timeouts, in ms */ +#define SQ905_CMD_TIMEOUT 500 +#define SQ905_DATA_TIMEOUT 1000 + +/* Maximum transfer size to use. */ +#define SQ905_MAX_TRANSFER 0x8000 +#define FRAME_HEADER_LEN 64 + +/* The known modes, or registers. These go in the "value" slot. */ + +/* 00 is "none" obviously */ + +#define SQ905_BULK_READ 0x03 /* precedes any bulk read */ +#define SQ905_COMMAND 0x06 /* precedes the command codes below */ +#define SQ905_PING 0x07 /* when reading an "idling" command */ +#define SQ905_READ_DONE 0xc0 /* ack bulk read completed */ + +/* Some command codes. These go in the "index" slot. */ + +#define SQ905_ID 0xf0 /* asks for model string */ +#define SQ905_CONFIG 0x20 /* gets photo alloc. table, not used here */ +#define SQ905_DATA 0x30 /* accesses photo data, not used here */ +#define SQ905_CLEAR 0xa0 /* clear everything */ +#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */ +#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */ +/* note that the capture command also controls the output dimensions */ +/* 0x60 -> 160x120, 0x61 -> 320x240 0x62 -> 640x480 depends on camera */ +/* 0x62 is not correct, at least for some cams. Should be 0x63 ? */ + +/* Structure to hold all of our device specific stuff */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + + u8 cam_type; + + /* + * Driver stuff + */ + struct work_struct work_struct; + struct workqueue_struct *work_thread; +}; + +/* The driver only supports 320x240 so far. */ +static struct v4l2_pix_format sq905_mode[1] = { + { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0} +}; + +struct cam_type { + u32 ident_word; + char *name; + struct v4l2_pix_format *min_mode; + u8 num_modes; + u8 sensor_flags; +}; + +#define SQ905_FLIP_HORIZ (1 << 0) +#define SQ905_FLIP_VERT (1 << 1) + +/* Last entry is default if nothing else matches */ +static struct cam_type cam_types[] = { + { 0x19010509, "PocketCam", &sq905_mode[0], 1, SQ905_FLIP_HORIZ }, + { 0x32010509, "Magpix", &sq905_mode[0], 1, SQ905_FLIP_HORIZ }, + { 0, "Default", &sq905_mode[0], 1, SQ905_FLIP_HORIZ | SQ905_FLIP_VERT } +}; + +/* + * Send a command to the camera. + */ +static int sq905_command(struct gspca_dev *gspca_dev, u16 index) +{ + int ret; + + gspca_dev->usb_buf[0] = '\0'; + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + SQ905_COMMAND, index, gspca_dev->usb_buf, 1, + SQ905_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", + __func__, ret); + return ret; + } + + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + SQ905_PING, 0, gspca_dev->usb_buf, 1, + SQ905_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed 2 (%d)", + __func__, ret); + return ret; + } + + return 0; +} + +/* + * Acknowledge the end of a frame - see warning on sq905_command. + */ +static int sq905_ack_frame(struct gspca_dev *gspca_dev) +{ + int ret; + + gspca_dev->usb_buf[0] = '\0'; + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1, + SQ905_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret); + return ret; + } + + return 0; +} + +/* + * request and read a block of data - see warning on sq905_command. + */ +static int +sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size) +{ + int ret; + int act_len; + + gspca_dev->usb_buf[0] = '\0'; + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + SQ905_BULK_READ, size, gspca_dev->usb_buf, + 1, SQ905_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret); + return ret; + } + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x81), + data, size, &act_len, SQ905_DATA_TIMEOUT); + + /* successful, it returns 0, otherwise negative */ + if (ret < 0 || act_len != size) { + PDEBUG(D_ERR, "bulk read fail (%d) len %d/%d", + ret, act_len, size); + return -EIO; + } + return 0; +} + +/* This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use the camera's USB interface we take the gspca + * usb_lock when performing USB operations. In practice the only thing we need + * to protect against is the usb_set_interface call that gspca makes during + * stream_off as the camera doesn't provide any controls that the user could try + * to change. + */ +static void sq905_dostream(struct work_struct *work) +{ + struct sd *dev = container_of(work, struct sd, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + struct gspca_frame *frame; + int bytes_left; /* bytes remaining in current frame. */ + int data_len; /* size to use for the next read. */ + int header_read; /* true if we have already read the frame header. */ + int discarding; /* true if we failed to get space for frame. */ + int packet_type; + int ret; + u8 *data; + u8 *buffer; + + buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + mutex_lock(&gspca_dev->usb_lock); + if (!buffer) { + PDEBUG(D_ERR, "Couldn't allocate USB buffer"); + goto quit_stream; + } + + while (gspca_dev->present && gspca_dev->streaming) { + /* Need a short delay to ensure streaming flag was set by + * gspca and to make sure gspca can grab the mutex. */ + mutex_unlock(&gspca_dev->usb_lock); + msleep(1); + + /* request some data and then read it until we have + * a complete frame. */ + bytes_left = sq905_mode[0].sizeimage + FRAME_HEADER_LEN; + header_read = 0; + discarding = 0; + + while (bytes_left > 0) { + data_len = bytes_left > SQ905_MAX_TRANSFER ? + SQ905_MAX_TRANSFER : bytes_left; + mutex_lock(&gspca_dev->usb_lock); + if (!gspca_dev->present) + goto quit_stream; + ret = sq905_read_data(gspca_dev, buffer, data_len); + if (ret < 0) + goto quit_stream; + mutex_unlock(&gspca_dev->usb_lock); + PDEBUG(D_STREAM, + "Got %d bytes out of %d for frame", + data_len, bytes_left); + bytes_left -= data_len; + data = buffer; + if (!header_read) { + packet_type = FIRST_PACKET; + /* The first 64 bytes of each frame are + * a header full of FF 00 bytes */ + data += FRAME_HEADER_LEN; + data_len -= FRAME_HEADER_LEN; + header_read = 1; + } else if (bytes_left == 0) { + packet_type = LAST_PACKET; + } else { + packet_type = INTER_PACKET; + } + frame = gspca_get_i_frame(gspca_dev); + if (frame && !discarding) + gspca_frame_add(gspca_dev, packet_type, + frame, data, data_len); + else + discarding = 1; + } + /* acknowledge the frame */ + mutex_lock(&gspca_dev->usb_lock); + if (!gspca_dev->present) + goto quit_stream; + ret = sq905_ack_frame(gspca_dev); + if (ret < 0) + goto quit_stream; + } +quit_stream: + /* the usb_lock is already acquired */ + if (gspca_dev->present) + sq905_command(gspca_dev, SQ905_CLEAR); + mutex_unlock(&gspca_dev->usb_lock); + kfree(buffer); +} + +/* This function is called at probe time just before sd_init */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam = &gspca_dev->cam; + struct sd *dev = (struct sd *) gspca_dev; + + cam->cam_mode = sq905_mode; + cam->nmodes = 1; + /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk_size = 64; + + INIT_WORK(&dev->work_struct, sq905_dostream); + + return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + /* This waits for sq905_dostream to finish */ + destroy_workqueue(dev->work_thread); + dev->work_thread = NULL; + mutex_lock(&gspca_dev->usb_lock); +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + u32 ident; + int ret; + + /* connect to the camera and read + * the model ID and process that and put it away. + */ + ret = sq905_command(gspca_dev, SQ905_CLEAR); + if (ret < 0) + return ret; + ret = sq905_command(gspca_dev, SQ905_ID); + if (ret < 0) + return ret; + ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4); + if (ret < 0) + return ret; + /* usb_buf is allocated with kmalloc so is aligned. */ + ident = le32_to_cpup((u32 *)gspca_dev->usb_buf); + ret = sq905_command(gspca_dev, SQ905_CLEAR); + if (ret < 0) + return ret; + dev->cam_type = 0; + while (dev->cam_type < ARRAY_SIZE(cam_types) - 1 && + ident != cam_types[dev->cam_type].ident_word) + dev->cam_type++; + PDEBUG(D_CONF, "SQ905 camera %s, ID %08x detected", + cam_types[dev->cam_type].name, ident); + return 0; +} + +/* Set up for getting frames. */ +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + int ret; + + /* "Open the shutter" and set size, to start capture */ + ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); + if (ret < 0) { + PDEBUG(D_ERR, "Start streaming command failed"); + return ret; + } + + /* Start the workqueue function to do the streaming */ + dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(dev->work_thread, &dev->work_struct); + + return 0; +} + +/* Table of supported USB devices */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x2770, 0x9120)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, +}; + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, + &sd_desc, + sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + PDEBUG(D_PROBE, "registered"); + return 0; +} + +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- cgit v1.2.3 From 9ddff42d7f7354e47e024a3b71bb84cf04158ad9 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 12 Feb 2009 12:05:45 +0100 Subject: gspca - main: More checks of the device disconnection. From: Jean-Francois Moine - prevent application oops when the device is disconnected - wake up the application at disconnection time - check the disconnection in ioctl dqbuf and poll Priority: high Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 105 ++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 31 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 64842682e..8d78b9287 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -136,11 +136,13 @@ static void fill_frame(struct gspca_dev *gspca_dev, cam_pkt_op pkt_scan; if (urb->status != 0) { + if (urb->status == -ESHUTDOWN) + return; /* disconnection */ #ifdef CONFIG_PM if (!gspca_dev->frozen) #endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); - return; /* disconnection ? */ + return; } pkt_scan = gspca_dev->sd_desc->pkt_scan; for (i = 0; i < urb->number_of_packets; i++) { @@ -220,6 +222,8 @@ static void bulk_irq(struct urb *urb) switch (urb->status) { case 0: break; + case -ESHUTDOWN: + return; /* disconnection */ case -ECONNRESET: urb->status = 0; break; @@ -228,7 +232,7 @@ static void bulk_irq(struct urb *urb) if (!gspca_dev->frozen) #endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); - return; /* disconnection ? */ + return; } /* check the availability of the frame buffer */ @@ -434,10 +438,8 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) if (urb == NULL) break; - BUG_ON(!gspca_dev->dev); gspca_dev->urb[i] = NULL; - if (!gspca_dev->present) - usb_kill_urb(urb); + usb_kill_urb(urb); if (urb->transfer_buffer != NULL) usb_buffer_free(gspca_dev->dev, urb->transfer_buffer_length, @@ -605,6 +607,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; + if (!gspca_dev->present) { + ret = -ENODEV; + goto out; + } + /* set the higher alternate setting and * loop until urb submit succeeds */ gspca_dev->alt = gspca_dev->nbalt; @@ -674,12 +681,14 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) static void gspca_stream_off(struct gspca_dev *gspca_dev) { gspca_dev->streaming = 0; - if (gspca_dev->present - && gspca_dev->sd_desc->stopN) - gspca_dev->sd_desc->stopN(gspca_dev); - destroy_urbs(gspca_dev); - if (gspca_dev->present) + if (gspca_dev->present) { + if (gspca_dev->sd_desc->stopN) + gspca_dev->sd_desc->stopN(gspca_dev); + destroy_urbs(gspca_dev); gspca_set_alt0(gspca_dev); + } + + /* always call stop0 to free the subdriver's resources */ if (gspca_dev->sd_desc->stop0) gspca_dev->sd_desc->stop0(gspca_dev); PDEBUG(D_STREAM, "stream off OK"); @@ -961,8 +970,17 @@ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct gspca_dev *gspca_dev = priv; + int ret; memset(cap, 0, sizeof *cap); + + /* protect the access to the usb device */ + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + if (!gspca_dev->present) { + ret = -ENODEV; + goto out; + } strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); if (gspca_dev->dev->product != NULL) { strncpy(cap->card, gspca_dev->dev->product, @@ -978,7 +996,10 @@ static int vidioc_querycap(struct file *file, void *priv, cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; - return 0; + ret = 0; +out: + mutex_unlock(&gspca_dev->usb_lock); + return ret; } static int vidioc_queryctrl(struct file *file, void *priv, @@ -1041,7 +1062,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = ctrls->set(gspca_dev, ctrl->value); + if (gspca_dev->present) + ret = ctrls->set(gspca_dev, ctrl->value); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1065,7 +1089,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv, return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = ctrls->get(gspca_dev, &ctrl->value); + if (gspca_dev->present) + ret = ctrls->get(gspca_dev, &ctrl->value); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1227,10 +1254,7 @@ static int vidioc_streamon(struct file *file, void *priv, return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; - if (!gspca_dev->present) { - ret = -ENODEV; - goto out; - } + if (gspca_dev->nframes == 0 || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { ret = -EINVAL; @@ -1298,7 +1322,10 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); + if (gspca_dev->present) + ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1313,7 +1340,10 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); + if (gspca_dev->present) + ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1332,7 +1362,11 @@ static int vidioc_g_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); + if (gspca_dev->present) + ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, + parm); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1357,7 +1391,11 @@ static int vidioc_s_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); + if (gspca_dev->present) + ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, + parm); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1531,7 +1569,8 @@ static int frame_wait(struct gspca_dev *gspca_dev, if (gspca_dev->sd_desc->dq_callback) { mutex_lock(&gspca_dev->usb_lock); - gspca_dev->sd_desc->dq_callback(gspca_dev); + if (gspca_dev->present) + gspca_dev->sd_desc->dq_callback(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); } return j; @@ -1553,6 +1592,9 @@ static int vidioc_dqbuf(struct file *file, void *priv, if (v4l2_buf->memory != gspca_dev->memory) return -EINVAL; + if (!gspca_dev->present) + return -ENODEV; + /* if not streaming, be sure the application will not loop forever */ if (!(file->f_flags & O_NONBLOCK) && !gspca_dev->streaming && gspca_dev->users == 1) @@ -1703,8 +1745,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) PDEBUG(D_FRAM, "poll"); poll_wait(file, &gspca_dev->wq, wait); - if (!gspca_dev->present) - return POLLERR; /* if reqbufs is not done, the user would use read() */ if (gspca_dev->nframes == 0) { @@ -1717,10 +1757,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) return POLLERR; - if (!gspca_dev->present) { - ret = POLLERR; - goto out; - } /* check the next incoming buffer */ i = gspca_dev->fr_o; @@ -1729,8 +1765,9 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) ret = POLLIN | POLLRDNORM; /* something to read */ else ret = 0; -out: mutex_unlock(&gspca_dev->queue_lock); + if (!gspca_dev->present) + return POLLHUP; return ret; } @@ -1956,10 +1993,16 @@ void gspca_disconnect(struct usb_interface *intf) mutex_lock(&gspca_dev->usb_lock); gspca_dev->present = 0; - mutex_unlock(&gspca_dev->usb_lock); - destroy_urbs(gspca_dev); + if (gspca_dev->streaming) { + destroy_urbs(gspca_dev); + wake_up_interruptible(&gspca_dev->wq); + } + + /* the device is freed at exit of this function */ gspca_dev->dev = NULL; + mutex_unlock(&gspca_dev->usb_lock); + usb_set_intfdata(intf, NULL); /* release the device */ -- cgit v1.2.3 From add4cca4f1bb659d08d75b45f57b226325a34a6b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 15:31:01 +0100 Subject: v4l2-dev: remove limit of 32 devices per driver in get_index() From: Hans Verkuil get_index() had a limitation of 32 devices per driver. This was unnecessarily strict and has been replaced with the maximum number of devices. That should really satisfy anyone! Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-dev.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 9e34e9ec2..e6dc1279a 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -326,37 +326,38 @@ static const struct file_operations v4l2_fops = { */ static int get_index(struct video_device *vdev, int num) { - u32 used = 0; - const int max_index = sizeof(used) * 8 - 1; + /* This can be static since this function is called with the global + videodev_lock held. */ + static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES); int i; - /* Currently a single v4l driver instance cannot create more than - 32 devices. - Increase to u64 or an array of u32 if more are needed. */ - if (num > max_index) { + if (num >= VIDEO_NUM_DEVICES) { printk(KERN_ERR "videodev: %s num is too large\n", __func__); return -EINVAL; } - /* Some drivers do not set the parent. In that case always return 0. */ + /* Some drivers do not set the parent. In that case always return + num or 0. */ if (vdev->parent == NULL) - return 0; + return num >= 0 ? num : 0; + + bitmap_zero(used, VIDEO_NUM_DEVICES); for (i = 0; i < VIDEO_NUM_DEVICES; i++) { if (video_device[i] != NULL && video_device[i]->parent == vdev->parent) { - used |= 1 << video_device[i]->index; + set_bit(video_device[i]->index, used); } } if (num >= 0) { - if (used & (1 << num)) + if (test_bit(num, used)) return -ENFILE; return num; } - i = ffz(used); - return i > max_index ? -ENFILE : i; + i = find_first_zero_bit(used, VIDEO_NUM_DEVICES); + return i == VIDEO_NUM_DEVICES ? -ENFILE : i; } int video_register_device(struct video_device *vdev, int type, int nr) -- cgit v1.2.3 From 398608cab6406080ef01e4cbfbd88a4c401f4fc0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 15:37:17 +0100 Subject: vivi: update comment to reflect that vivi can now create more than 32 devs. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vivi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 603274874..e089cbd27 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -1348,10 +1348,7 @@ static struct video_device vivi_template = { The real maximum number of virtual drivers will depend on how many drivers will succeed. This is limited to the maximum number of devices that - videodev supports. Since there are 64 minors for video grabbers, this is - currently the theoretical maximum limit. However, a further limit does - exist at videodev that forbids any driver to register more than 32 video - grabbers. + videodev supports, which is equal to VIDEO_NUM_DEVICES. */ static int __init vivi_init(void) { -- cgit v1.2.3 From 9511f472cfb47c53ad0f210dd137dedfb753cea7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 15:54:23 +0100 Subject: v4l2-device: allow a NULL parent device when registering. From: Hans Verkuil Some drivers (e.g. for ISA devices) have no parent device because there is no associated bus driver. Allow the parent device to be NULL in those cases when registering v4l2_device. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-device.c | 37 +++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index e84925976..cb8234437 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -27,15 +27,24 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) { - if (dev == NULL || v4l2_dev == NULL) + if (v4l2_dev == NULL) return -EINVAL; - /* Warn if we apparently re-register a device */ - WARN_ON(dev_get_drvdata(dev) != NULL); + INIT_LIST_HEAD(&v4l2_dev->subdevs); spin_lock_init(&v4l2_dev->lock); v4l2_dev->dev = dev; - snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", + if (dev == NULL) { + /* If dev == NULL, then name must be filled in by the caller */ + WARN_ON(!v4l2_dev->name[0]); + return 0; + } + + /* Set name to driver name + device name if it is empty. */ + if (!v4l2_dev->name[0]) + snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", dev->driver->name, dev_name(dev)); + if (dev_get_drvdata(dev)) + v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n"); dev_set_drvdata(dev, v4l2_dev); return 0; } @@ -45,10 +54,11 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) { struct v4l2_subdev *sd, *next; - if (v4l2_dev == NULL || v4l2_dev->dev == NULL) + if (v4l2_dev == NULL) return; - dev_set_drvdata(v4l2_dev->dev, NULL); - /* unregister subdevs */ + if (v4l2_dev->dev) + dev_set_drvdata(v4l2_dev->dev, NULL); + /* Unregister subdevs */ list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) v4l2_device_unregister_subdev(sd); @@ -56,19 +66,20 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) } EXPORT_SYMBOL_GPL(v4l2_device_unregister); -int v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd) +int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, + struct v4l2_subdev *sd) { /* Check for valid input */ - if (dev == NULL || sd == NULL || !sd->name[0]) + if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) return -EINVAL; /* Warn if we apparently re-register a subdev */ WARN_ON(sd->dev != NULL); if (!try_module_get(sd->owner)) return -ENODEV; - sd->dev = dev; - spin_lock(&dev->lock); - list_add_tail(&sd->list, &dev->subdevs); - spin_unlock(&dev->lock); + sd->dev = v4l2_dev; + spin_lock(&v4l2_dev->lock); + list_add_tail(&sd->list, &v4l2_dev->subdevs); + spin_unlock(&v4l2_dev->lock); return 0; } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); -- cgit v1.2.3 From 951bf44feee86f832f1b68efe05395dfee73a15c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 16:00:53 +0100 Subject: v4l2-subdev: rename dev field to v4l2_dev From: Hans Verkuil Remain consistent in the naming: fields pointing to v4l2_device should be called v4l2_dev. There are too many device-like entities without adding to the confusion by mixing naming conventions. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-device.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index cb8234437..35e42e947 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -73,10 +73,10 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) return -EINVAL; /* Warn if we apparently re-register a subdev */ - WARN_ON(sd->dev != NULL); + WARN_ON(sd->v4l2_dev != NULL); if (!try_module_get(sd->owner)) return -ENODEV; - sd->dev = v4l2_dev; + sd->v4l2_dev = v4l2_dev; spin_lock(&v4l2_dev->lock); list_add_tail(&sd->list, &v4l2_dev->subdevs); spin_unlock(&v4l2_dev->lock); @@ -87,12 +87,12 @@ EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) { /* return if it isn't registered */ - if (sd == NULL || sd->dev == NULL) + if (sd == NULL || sd->v4l2_dev == NULL) return; - spin_lock(&sd->dev->lock); + spin_lock(&sd->v4l2_dev->lock); list_del(&sd->list); - spin_unlock(&sd->dev->lock); - sd->dev = NULL; + spin_unlock(&sd->v4l2_dev->lock); + sd->v4l2_dev = NULL; module_put(sd->owner); } EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev); -- cgit v1.2.3 From f9bd48b87f02902de6b355af1489669baaad39b5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 17:23:12 +0100 Subject: vivi: introduce v4l2_device and do several cleanups From: Hans Verkuil - add v4l2_device - remove BKL - make the debug parameter settable on the fly - set bus_info in querycap Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vivi.c | 258 ++++++++++++++++++++------------------- 1 file changed, 130 insertions(+), 128 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index e089cbd27..e4cb33ca0 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -34,14 +34,15 @@ #include #endif #include -#include -#include -#include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) #include #endif +#include +#include +#include +#include "font.h" #define VIVI_MODULE_NAME "vivi" @@ -50,18 +51,32 @@ #define WAKE_DENOMINATOR 1001 #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ -#include "font.h" - #define VIVI_MAJOR_VERSION 0 -#define VIVI_MINOR_VERSION 5 +#define VIVI_MINOR_VERSION 6 #define VIVI_RELEASE 0 #define VIVI_VERSION \ KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) -/* Declare static vars that will be used as parameters */ -static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ -static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ -static int n_devs = 1; /* Number of virtual devices */ +MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); +MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); +MODULE_LICENSE("Dual BSD/GPL"); + +static unsigned video_nr = -1; +module_param(video_nr, uint, 0644); +MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect"); + +static unsigned n_devs = 1; +module_param(n_devs, uint, 0644); +MODULE_PARM_DESC(n_devs, "number of video devices to create"); + +static unsigned debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + +static unsigned int vid_limit = 16; +module_param(vid_limit, uint, 0644); +MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); + /* supported controls */ static struct v4l2_queryctrl vivi_qctrl[] = { @@ -115,11 +130,8 @@ static struct v4l2_queryctrl vivi_qctrl[] = { static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; -#define dprintk(dev, level, fmt, arg...) \ - do { \ - if (dev->vfd->debug >= (level)) \ - printk(KERN_DEBUG "vivi: " fmt , ## arg); \ - } while (0) +#define dprintk(dev, level, fmt, arg...) \ + v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) /* ------------------------------------------------------------------ Basic structures @@ -209,6 +221,7 @@ static LIST_HEAD(vivi_devlist); struct vivi_dev { struct list_head vivi_devlist; + struct v4l2_device v4l2_dev; spinlock_t slock; struct mutex mutex; @@ -659,7 +672,7 @@ static int vivi_start_thread(struct vivi_fh *fh) dma_q->kthread = kthread_run(vivi_thread, fh, "vivi"); if (IS_ERR(dma_q->kthread)) { - printk(KERN_ERR "vivi: kernel_thread() failed\n"); + v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); return PTR_ERR(dma_q->kthread); } /* Wakes thread */ @@ -802,8 +815,12 @@ static struct videobuf_queue_ops vivi_video_qops = { static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; + strcpy(cap->driver, "vivi"); strcpy(cap->card, "vivi"); + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); cap->version = VIVI_VERSION; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | @@ -1127,32 +1144,21 @@ static int vidioc_s_ctrl(struct file *file, void *priv, static int vivi_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct vivi_dev *dev; + struct vivi_dev *dev = video_drvdata(file); struct vivi_fh *fh = NULL; int i; int retval = 0; - printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor); - - lock_kernel(); - list_for_each_entry(dev, &vivi_devlist, vivi_devlist) - if (dev->vfd->minor == minor) - goto found; - unlock_kernel(); - return -ENODEV; - -found: mutex_lock(&dev->mutex); dev->users++; if (dev->users > 1) { dev->users--; - retval = -EBUSY; - goto unlock; + mutex_unlock(&dev->mutex); + return -EBUSY; } - dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor, + dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num, v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); /* allocate + initialize per filehandle data */ @@ -1160,14 +1166,11 @@ found: if (NULL == fh) { dev->users--; retval = -ENOMEM; - goto unlock; } -unlock: mutex_unlock(&dev->mutex); - if (retval) { - unlock_kernel(); + + if (retval) return retval; - } file->private_data = fh; fh->dev = dev; @@ -1196,7 +1199,6 @@ unlock: sizeof(struct vivi_buffer), fh); vivi_start_thread(fh); - unlock_kernel(); return 0; } @@ -1252,32 +1254,6 @@ static int vivi_close(struct file *file) return 0; } -static int vivi_release(void) -{ - struct vivi_dev *dev; - struct list_head *list; - - while (!list_empty(&vivi_devlist)) { - list = vivi_devlist.next; - list_del(list); - dev = list_entry(list, struct vivi_dev, vivi_devlist); - - if (-1 != dev->vfd->minor) { - printk(KERN_INFO "%s: unregistering /dev/video%d\n", - VIVI_MODULE_NAME, dev->vfd->num); - video_unregister_device(dev->vfd); - } else { - printk(KERN_INFO "%s: releasing /dev/video%d\n", - VIVI_MODULE_NAME, dev->vfd->num); - video_device_release(dev->vfd); - } - - kfree(dev); - } - - return 0; -} - static int vivi_mmap(struct file *file, struct vm_area_struct *vma) { struct vivi_fh *fh = file->private_data; @@ -1340,84 +1316,126 @@ static struct video_device vivi_template = { .tvnorms = V4L2_STD_525_60, .current_norm = V4L2_STD_NTSC_M, }; + /* ----------------------------------------------------------------- Initialization and module stuff ------------------------------------------------------------------*/ -/* This routine allocates from 1 to n_devs virtual drivers. +static int vivi_release(void) +{ + struct vivi_dev *dev; + struct list_head *list; - The real maximum number of virtual drivers will depend on how many drivers - will succeed. This is limited to the maximum number of devices that - videodev supports, which is equal to VIDEO_NUM_DEVICES. - */ -static int __init vivi_init(void) + while (!list_empty(&vivi_devlist)) { + list = vivi_devlist.next; + list_del(list); + dev = list_entry(list, struct vivi_dev, vivi_devlist); + + v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n", + dev->vfd->num); + video_unregister_device(dev->vfd); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); + } + + return 0; +} + +static int __init vivi_create_instance(int i) { - int ret = -ENOMEM, i; struct vivi_dev *dev; struct video_device *vfd; + int ret; - if (n_devs <= 0) - n_devs = 1; + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; - for (i = 0; i < n_devs; i++) { - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - break; + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), + "%s-%03d", VIVI_MODULE_NAME, i); + ret = v4l2_device_register(NULL, &dev->v4l2_dev); + if (ret) + goto free_dev; - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - init_waitqueue_head(&dev->vidq.wq); + /* init video dma queues */ + INIT_LIST_HEAD(&dev->vidq.active); + init_waitqueue_head(&dev->vidq.wq); - /* initialize locks */ - spin_lock_init(&dev->slock); - mutex_init(&dev->mutex); + /* initialize locks */ + spin_lock_init(&dev->slock); + mutex_init(&dev->mutex); - vfd = video_device_alloc(); - if (!vfd) { - kfree(dev); - break; - } + ret = -ENOMEM; + vfd = video_device_alloc(); + if (!vfd) + goto unreg_dev; - *vfd = vivi_template; + *vfd = vivi_template; - ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); - if (ret < 0) { - video_device_release(vfd); - kfree(dev); + ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); + if (ret < 0) + goto rel_vdev; - /* If some registers succeeded, keep driver */ - if (i) - ret = 0; + video_set_drvdata(vfd, dev); - break; - } + /* Now that everything is fine, let's add it to device list */ + list_add_tail(&dev->vivi_devlist, &vivi_devlist); - /* Now that everything is fine, let's add it to device list */ - list_add_tail(&dev->vivi_devlist, &vivi_devlist); + snprintf(vfd->name, sizeof(vfd->name), "%s (%i)", + vivi_template.name, vfd->num); - snprintf(vfd->name, sizeof(vfd->name), "%s (%i)", - vivi_template.name, vfd->minor); + if (video_nr >= 0) + video_nr++; - if (video_nr >= 0) - video_nr++; + dev->vfd = vfd; + v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n", + vfd->num); + return 0; + +rel_vdev: + video_device_release(vfd); +unreg_dev: + v4l2_device_unregister(&dev->v4l2_dev); +free_dev: + kfree(dev); + return ret; +} - dev->vfd = vfd; - printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n", - VIVI_MODULE_NAME, vfd->num); +/* This routine allocates from 1 to n_devs virtual drivers. + + The real maximum number of virtual drivers will depend on how many drivers + will succeed. This is limited to the maximum number of devices that + videodev supports, which is equal to VIDEO_NUM_DEVICES. + */ +static int __init vivi_init(void) +{ + int ret, i; + + if (n_devs <= 0) + n_devs = 1; + + for (i = 0; i < n_devs; i++) { + ret = vivi_create_instance(i); + if (ret) { + /* If some instantiations succeeded, keep driver */ + if (i) + ret = 0; + break; + } } if (ret < 0) { - vivi_release(); printk(KERN_INFO "Error %d while loading vivi driver\n", ret); - } else { - printk(KERN_INFO "Video Technology Magazine Virtual Video " + return ret; + } + + printk(KERN_INFO "Video Technology Magazine Virtual Video " "Capture Board ver %u.%u.%u successfully loaded.\n", (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF, VIVI_VERSION & 0xFF); - /* n_devs will reflect the actual number of allocated devices */ - n_devs = i; - } + /* n_devs will reflect the actual number of allocated devices */ + n_devs = i; return ret; } @@ -1429,19 +1447,3 @@ static void __exit vivi_exit(void) module_init(vivi_init); module_exit(vivi_exit); - -MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); -MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); -MODULE_LICENSE("Dual BSD/GPL"); - -module_param(video_nr, uint, 0444); -MODULE_PARM_DESC(video_nr, "video iminor start number"); - -module_param(n_devs, uint, 0444); -MODULE_PARM_DESC(n_devs, "number of video devices to create"); - -module_param_named(debug, vivi_template.debug, int, 0444); -MODULE_PARM_DESC(debug, "activates debug info"); - -module_param(vid_limit, int, 0644); -MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); -- cgit v1.2.3 From c70e5dd6b23d260a1294ff4b23f49ccd78999c86 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 17:43:44 +0100 Subject: vivi: controls are per-device, not global. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vivi.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index e4cb33ca0..207dfa58f 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -128,8 +128,6 @@ static struct v4l2_queryctrl vivi_qctrl[] = { } }; -static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; - #define dprintk(dev, level, fmt, arg...) \ v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) @@ -242,6 +240,9 @@ struct vivi_dev { /* Input Number */ int input; + + /* Control 'registers' */ + int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; }; struct vivi_fh { @@ -1111,12 +1112,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; int i; for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) if (ctrl->id == vivi_qctrl[i].id) { - ctrl->value = qctl_regs[i]; - return (0); + ctrl->value = dev->qctl_regs[i]; + return 0; } return -EINVAL; @@ -1124,16 +1127,18 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; int i; for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) if (ctrl->id == vivi_qctrl[i].id) { - if (ctrl->value < vivi_qctrl[i].minimum - || ctrl->value > vivi_qctrl[i].maximum) { - return (-ERANGE); - } - qctl_regs[i] = ctrl->value; - return (0); + if (ctrl->value < vivi_qctrl[i].minimum || + ctrl->value > vivi_qctrl[i].maximum) { + return -ERANGE; + } + dev->qctl_regs[i] = ctrl->value; + return 0; } return -EINVAL; } @@ -1146,7 +1151,6 @@ static int vivi_open(struct file *file) { struct vivi_dev *dev = video_drvdata(file); struct vivi_fh *fh = NULL; - int i; int retval = 0; mutex_lock(&dev->mutex); @@ -1180,10 +1184,6 @@ static int vivi_open(struct file *file) fh->width = 640; fh->height = 480; - /* Put all controls at a sane state */ - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - qctl_regs[i] = vivi_qctrl[i].default_value; - /* Resets frame counters */ dev->h = 0; dev->m = 0; @@ -1341,18 +1341,18 @@ static int vivi_release(void) return 0; } -static int __init vivi_create_instance(int i) +static int __init vivi_create_instance(int inst) { struct vivi_dev *dev; struct video_device *vfd; - int ret; + int ret, i; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), - "%s-%03d", VIVI_MODULE_NAME, i); + "%s-%03d", VIVI_MODULE_NAME, inst); ret = v4l2_device_register(NULL, &dev->v4l2_dev); if (ret) goto free_dev; @@ -1378,6 +1378,10 @@ static int __init vivi_create_instance(int i) video_set_drvdata(vfd, dev); + /* Set all controls to their default value. */ + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + dev->qctl_regs[i] = vivi_qctrl[i].default_value; + /* Now that everything is fine, let's add it to device list */ list_add_tail(&dev->vivi_devlist, &vivi_devlist); -- cgit v1.2.3 From 9446aad394fc912dc47f17e7638357edfd470ded Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 17:50:19 +0100 Subject: vivi: add slider flag to controls. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vivi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 207dfa58f..76f7dfc32 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -87,7 +87,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 65535, .step = 65535/100, .default_value = 65535, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, .type = V4L2_CTRL_TYPE_INTEGER, }, { .id = V4L2_CID_BRIGHTNESS, @@ -97,7 +97,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 255, .step = 1, .default_value = 127, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, }, { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -106,7 +106,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 255, .step = 0x1, .default_value = 0x10, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, }, { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, @@ -115,7 +115,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 255, .step = 0x1, .default_value = 127, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, }, { .id = V4L2_CID_HUE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -124,7 +124,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 127, .step = 0x1, .default_value = 0, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, } }; -- cgit v1.2.3 From bdff40c8e0a3b0971c67f28db1b0f9b2fe581313 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 14 Feb 2009 23:26:56 +0100 Subject: uvcvideo: Initialize streaming parameters with the probe control value From: Laurent Pinchart The UVC specification requires SET_CUR requests on the streaming commit control to use values retrieved from a successful GET_CUR request on the probe control. Initialize streaming parameters with the probe control current value to make sure the driver always complies. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_video.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 04c791213..a4034ccb2 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -1030,11 +1030,20 @@ int uvc_video_init(struct uvc_video_device *video) */ usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); - /* Some webcams don't suport GET_DEF requests on the probe control. We - * fall back to GET_CUR if GET_DEF fails. + /* Set the streaming probe control with default streaming parameters + * retrieved from the device. Webcams that don't suport GET_DEF + * requests on the probe control will just keep their current streaming + * parameters. */ - if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && - (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) + if (uvc_get_video_ctrl(video, probe, 1, GET_DEF) == 0) + uvc_set_video_ctrl(video, probe, 1); + + /* Initialize the streaming parameters with the probe control current + * value. This makes sure SET_CUR requests on the streaming commit + * control will always use values retrieved from a successful GET_CUR + * request on the probe control, as required by the UVC specification. + */ + if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) return ret; /* Check if the default format descriptor exists. Use the first -- cgit v1.2.3 From e2a760f26ff7124de2bc6bed4647962dd7078d1b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 14 Feb 2009 23:39:08 +0100 Subject: uvcvideo: Ignore empty bulk URBs From: Laurent Pinchart Devices may send a zero-length packet to signal the end of a bulk payload. If the payload size is a multiple of the URB size the zero-length packet will be received by the URB completion handler. Handle this by ignoring all empty URBs. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_video.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index a4034ccb2..328910855 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -540,6 +540,9 @@ static void uvc_video_decode_bulk(struct urb *urb, u8 *mem; int len, ret; + if (urb->actual_length == 0) + return; + mem = urb->transfer_buffer; len = urb->actual_length; video->bulk.payload_size += len; -- cgit v1.2.3 From b25818a3a4e324f54c59786922c73867af099253 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 16 Feb 2009 21:41:52 +0100 Subject: uvcvideo: Add quirk to override wrong bandwidth value for Vimicro devices From: Laurent Pinchart At least 3 Vimicro cameras (0x332d, 0x3410 and 0x3420) fail to return correct bandwidth information. The first model rounds the value provided by the host to the nearest supported packet size, while the other two always request the maximum bandwidth. Introduce a device quirk to override the value returned by the device with an estimated bandwidth computed by the driver from the frame size and frame rate, and enable it for all Vimicro cameras. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 9 ++++++++ linux/drivers/media/video/uvc/uvc_video.c | 34 ++++++++++++++++++++++++++---- linux/drivers/media/video/uvc/uvcvideo.h | 1 + 3 files changed, 40 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 2a41eb418..0d2d87198 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1863,6 +1863,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, + /* ViMicro */ + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0ac8, + .idProduct = 0x0000, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, /* MT6227 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 328910855..82a9999b6 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -61,7 +61,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, return 0; } -static void uvc_fixup_buffer_size(struct uvc_video_device *video, +static void uvc_fixup_video_ctrl(struct uvc_video_device *video, struct uvc_streaming_control *ctrl) { struct uvc_format *format; @@ -84,6 +84,31 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video, video->dev->uvc_version < 0x0110)) ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize; + + if (video->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && + video->streaming->intf->num_altsetting > 1) { + u32 interval; + u32 bandwidth; + + interval = (ctrl->dwFrameInterval > 100000) + ? ctrl->dwFrameInterval + : frame->dwFrameInterval[0]; + + /* Compute a bandwidth estimation by multiplying the frame + * size by the number of video frames per second, divide the + * result by the number of USB frames (or micro-frames for + * high-speed devices) per second and add the UVC header size + * (assumed to be 12 bytes long). + */ + bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; + bandwidth *= 10000000 / interval + 1; + bandwidth /= 1000; + if (video->dev->udev->speed == USB_SPEED_HIGH) + bandwidth /= 8; + bandwidth += 12; + + ctrl->dwMaxPayloadTransferSize = bandwidth; + } } static int uvc_get_video_ctrl(struct uvc_video_device *video, @@ -158,10 +183,11 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ctrl->bMaxVersion = 0; } - /* Some broken devices return a null or wrong dwMaxVideoFrameSize. - * Try to get the value from the format and frame descriptors. + /* Some broken devices return null or wrong dwMaxVideoFrameSize and + * dwMaxPayloadTransferSize fields. Try to get the value from the + * format and frame descriptors. */ - uvc_fixup_buffer_size(video, ctrl); + uvc_fixup_video_ctrl(video, ctrl); ret = 0; out: diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 408b8b846..53d5c9e0c 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -315,6 +315,7 @@ struct uvc_xu_control { #define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 #define UVC_QUIRK_PRUNE_CONTROLS 0x00000040 +#define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 -- cgit v1.2.3 From 538850e6819a36200323bf1469eb8544e4f4e0c6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Feb 2009 13:46:22 +0000 Subject: Drop test for kernel version 2.6.15 From: Jean Delvare The v4l-dvb repository supports kernel versions 2.6.16 and later only, so no need to test for kernel version 2.6.15. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 88a365ad9..ca7609583 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1507,9 +1507,6 @@ static void af9015_usb_device_exit(struct usb_interface *intf) /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver af9015_usb_driver = { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15) - .owner = THIS_MODULE, -#endif .name = "dvb_usb_af9015", .probe = af9015_usb_probe, .disconnect = af9015_usb_device_exit, -- cgit v1.2.3 From ea5c2ae318fda3731d4fe711b704122a62a7dce9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Feb 2009 10:11:10 +0100 Subject: [PATCH] V4L: missing parentheses? From: Roel Kluin Add missing parentheses Signed-off-by: Roel Kluin Acked-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tda18271-common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tda18271-common.c b/linux/drivers/media/common/tuners/tda18271-common.c index a8fb96698..a49facb7b 100644 --- a/linux/drivers/media/common/tuners/tda18271-common.c +++ b/linux/drivers/media/common/tuners/tda18271-common.c @@ -558,9 +558,9 @@ int tda18271_set_standby_mode(struct dvb_frontend *fe, tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt); regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */ - regs[R_EP3] |= sm ? (1 << 7) : 0 | - sm_lt ? (1 << 6) : 0 | - sm_xt ? (1 << 5) : 0; + regs[R_EP3] |= (sm ? (1 << 7) : 0) | + (sm_lt ? (1 << 6) : 0) | + (sm_xt ? (1 << 5) : 0); return tda18271_write_regs(fe, R_EP3, 1); } -- cgit v1.2.3 From 0e80661eedb37a2d8810e6de027c2530db814c27 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 16:22:16 +0100 Subject: saa7115: don't access reg 0x87 if it is not present. From: Hans Verkuil Devices like the saa7111 do not have this register, so check for this before using it. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7115.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 9fbb93775..2e868fade 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1309,11 +1309,12 @@ static int saa711x_s_stream(struct v4l2_subdev *sd, int enable) v4l2_dbg(1, debug, sd, "%s output\n", enable ? "enable" : "disable"); - if (state->enable != enable) { - state->enable = enable; - saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, - state->enable); - } + if (state->enable == enable) + return 0; + state->enable = enable; + if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED)) + return 0; + saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable); return 0; } -- cgit v1.2.3 From 6fdf67ebdaa0672d9f580433d4331b451ada01bd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 16:23:38 +0100 Subject: saa7185: add colorbar support. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7185.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c index 195e2f415..68bec4d5d 100644 --- a/linux/drivers/media/video/saa7185.c +++ b/linux/drivers/media/video/saa7185.c @@ -282,6 +282,8 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) switch (*iarg) { case 0: + /* turn off colorbar */ + saa7185_write(client, 0x3a, 0x0f); /* Switch RTCE to 1 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); @@ -289,6 +291,8 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) break; case 1: + /* turn off colorbar */ + saa7185_write(client, 0x3a, 0x0f); /* Switch RTCE to 0 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); @@ -296,6 +300,16 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) saa7185_write(client, 0x6e, 0x00); break; + case 2: + /* turn on colorbar */ + saa7185_write(client, 0x3a, 0x8f); + /* Switch RTCE to 0 */ + saa7185_write(client, 0x61, + (encoder->reg[0x61] & 0xf7) | 0x08); + /* SW: a slight sync problem... */ + saa7185_write(client, 0x6e, 0x01); + break; + default: return -EINVAL; } -- cgit v1.2.3 From d508d21a881363ed8a29131a5d766a17562d9596 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 16:35:33 +0100 Subject: saa7115: add querystd and g_input_status support for zoran. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7115.c | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 2e868fade..169b01f6d 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1372,6 +1372,47 @@ static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_dat } } +static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + struct saa711x_state *state = to_state(sd); + int reg1e; + + *std = V4L2_STD_ALL; + if (state->ident != V4L2_IDENT_SAA7115) + return 0; + reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); + + switch (reg1e & 0x03) { + case 1: + *std = V4L2_STD_NTSC; + break; + case 2: + *std = V4L2_STD_PAL; + break; + case 3: + *std = V4L2_STD_SECAM; + break; + default: + break; + } + return 0; +} + +static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + struct saa711x_state *state = to_state(sd); + int reg1e = 0x80; + int reg1f; + + *status = V4L2_IN_ST_NO_SIGNAL; + if (state->ident == V4L2_IDENT_SAA7115) + reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); + reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); + if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80) + *status = 0; + return 0; +} + #ifdef CONFIG_VIDEO_ADV_DEBUG static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { @@ -1495,6 +1536,8 @@ static const struct v4l2_subdev_video_ops saa711x_video_ops = { .g_vbi_data = saa711x_g_vbi_data, .decode_vbi_line = saa711x_decode_vbi_line, .s_stream = saa711x_s_stream, + .querystd = saa711x_querystd, + .g_input_status = saa711x_g_input_status, }; static const struct v4l2_subdev_ops saa711x_ops = { -- cgit v1.2.3 From 01293c4d013ac24226a4b52660d28c2fe85fe3fa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:13:31 +0100 Subject: zoran: convert to video_ioctl2 and remove 'ready_to_be_freed' hack. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran.h | 2 - linux/drivers/media/video/zoran/zoran_driver.c | 2557 +++++++++++------------- 2 files changed, 1114 insertions(+), 1445 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran.h b/linux/drivers/media/video/zoran/zoran.h index e873a9162..1bf540cb5 100644 --- a/linux/drivers/media/video/zoran/zoran.h +++ b/linux/drivers/media/video/zoran/zoran.h @@ -312,7 +312,6 @@ struct zoran_jpg_struct { struct zoran_jpg_buffer buffer[BUZ_MAX_FRAME]; /* buffers */ int num_buffers, buffer_size; u8 allocated; /* Flag if buffers are allocated */ - u8 ready_to_be_freed; /* hack - see zoran_driver.c */ u8 need_contiguous; /* Flag if contiguous buffers are needed */ }; @@ -321,7 +320,6 @@ struct zoran_v4l_struct { struct zoran_v4l_buffer buffer[VIDEO_MAX_FRAME]; /* buffers */ int num_buffers, buffer_size; u8 allocated; /* Flag if buffers are allocated */ - u8 ready_to_be_freed; /* hack - see zoran_driver.c */ }; struct zoran; diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 798745c0a..afbb18b89 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -321,11 +321,6 @@ v4l_fbuffer_alloc (struct file *file) unsigned long pmem = 0; #endif - /* we might have old buffers lying around... */ - if (fh->v4l_buffers.ready_to_be_freed) { - v4l_fbuffer_free(file); - } - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { if (fh->v4l_buffers.buffer[i].fbuffer) dprintk(2, @@ -486,7 +481,6 @@ v4l_fbuffer_free (struct file *file) } fh->v4l_buffers.allocated = 0; - fh->v4l_buffers.ready_to_be_freed = 0; } /* @@ -531,11 +525,6 @@ jpg_fbuffer_alloc (struct file *file) int i, j, off; unsigned long mem; - /* we might have old buffers lying around */ - if (fh->jpg_buffers.ready_to_be_freed) { - jpg_fbuffer_free(file); - } - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) { if (fh->jpg_buffers.buffer[i].frag_tab) dprintk(2, @@ -678,7 +667,6 @@ jpg_fbuffer_free (struct file *file) } fh->jpg_buffers.allocated = 0; - fh->jpg_buffers.ready_to_be_freed = 0; } /* @@ -722,7 +710,7 @@ zoran_v4l_set_format (struct file *file, if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) { dprintk(1, KERN_ERR - "%s: v4l_set_format() - wrong frame alingment\n", + "%s: v4l_set_format() - wrong frame alignment\n", ZR_DEVNAME(zr)); return -EINVAL; } @@ -1187,7 +1175,6 @@ zoran_open_init_session (struct file *file) fh->v4l_buffers.buffer[i].bs.frame = i; } fh->v4l_buffers.allocated = 0; - fh->v4l_buffers.ready_to_be_freed = 0; fh->v4l_buffers.active = ZORAN_FREE; fh->v4l_buffers.buffer_size = v4l_bufsize; fh->v4l_buffers.num_buffers = v4l_nbufs; @@ -1203,7 +1190,6 @@ zoran_open_init_session (struct file *file) } fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous; fh->jpg_buffers.allocated = 0; - fh->jpg_buffers.ready_to_be_freed = 0; fh->jpg_buffers.active = ZORAN_FREE; fh->jpg_buffers.buffer_size = jpg_bufsize; fh->jpg_buffers.num_buffers = jpg_nbufs; @@ -1237,10 +1223,8 @@ zoran_close_end_session (struct file *file) } /* v4l buffers */ - if (fh->v4l_buffers.allocated || - fh->v4l_buffers.ready_to_be_freed) { + if (fh->v4l_buffers.allocated) v4l_fbuffer_free(file); - } /* jpg capture */ if (fh->jpg_buffers.active != ZORAN_FREE) { @@ -1251,10 +1235,8 @@ zoran_close_end_session (struct file *file) } /* jpg buffers */ - if (fh->jpg_buffers.allocated || - fh->jpg_buffers.ready_to_be_freed) { + if (fh->jpg_buffers.allocated) jpg_fbuffer_free(file); - } } /* @@ -1968,38 +1950,13 @@ zoran_set_input (struct zoran *zr, * ioctl routine */ -static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) { - struct zoran_fh *fh = file->private_data; + struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - /* CAREFUL: used in multiple places here */ struct zoran_jpg_settings settings; - /* we might have older buffers lying around... We don't want - * to wait, but we do want to try cleaning them up ASAP. So - * we try to obtain the lock and free them. If that fails, we - * don't do anything and wait for the next turn. In the end, - * zoran_close() or a new allocation will still free them... - * This is just a 'the sooner the better' extra 'feature' - * - * We don't free the buffers right on munmap() because that - * causes oopses (kfree() inside munmap() oopses for no - * apparent reason - it's also not reproduceable in any way, - * but moving the free code outside the munmap() handler fixes - * all this... If someone knows why, please explain me (Ronald) - */ - if (mutex_trylock(&zr->resource_lock)) { - /* we obtained it! Let's try to free some things */ - if (fh->jpg_buffers.ready_to_be_freed) - jpg_fbuffer_free(file); - if (fh->v4l_buffers.ready_to_be_freed) - v4l_fbuffer_free(file); - - mutex_unlock(&zr->resource_lock); - } - switch (cmd) { - case VIDIOCGCAP: { struct video_capability *vcap = arg; @@ -2021,7 +1978,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; case VIDIOCGCHAN: { @@ -2052,7 +2008,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says: * @@ -2082,11 +2037,10 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* Make sure the changes come into effect */ res = wait_grab_pending(zr); - schan_unlock_and_return: +schan_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; } - break; case VIDIOCGPICT: { @@ -2110,7 +2064,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; case VIDIOCSPICT: { @@ -2156,7 +2109,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; case VIDIOCCAPTURE: { @@ -2171,7 +2123,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case VIDIOCGWIN: { @@ -2189,7 +2140,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) vwin->clipcount = 0; return 0; } - break; case VIDIOCSWIN: { @@ -2211,7 +2161,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case VIDIOCGFBUF: { @@ -2224,7 +2173,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) mutex_unlock(&zr->resource_lock); return 0; } - break; case VIDIOCSFBUF: { @@ -2257,7 +2205,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case VIDIOCSYNC: { @@ -2273,7 +2220,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) zr->v4l_sync_tail++; return res; } - break; case VIDIOCMCAPTURE: { @@ -2291,7 +2237,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) mutex_unlock(&zr->resource_lock); return res; } - break; case VIDIOCGMBUF: { @@ -2327,12 +2272,11 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* The next mmap will map the V4L buffers */ fh->map_mode = ZORAN_MAP_MODE_RAW; - v4l1reqbuf_unlock_and_return: +v4l1reqbuf_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; } - break; case VIDIOCGUNIT: { @@ -2348,7 +2292,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; /* * RJ: In principal we could support subcaptures for V4L grabbing. @@ -2362,7 +2305,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) ZR_DEVNAME(zr)); return -EINVAL; } - break; case VIDIOCSCAPTURE: { @@ -2370,7 +2312,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) ZR_DEVNAME(zr)); return -EINVAL; } - break; case BUZIOC_G_PARAMS: { @@ -2417,7 +2358,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; case BUZIOC_S_PARAMS: { @@ -2466,12 +2406,11 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) } fh->jpg_settings = settings; - sparams_unlock_and_return: +sparams_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; } - break; case BUZIOC_REQBUFS: { @@ -2521,12 +2460,11 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* The next mmap will map the MJPEG buffers - could * also be *_PLAY, but it doesn't matter here */ fh->map_mode = ZORAN_MAP_MODE_JPG_REC; - jpgreqbuf_unlock_and_return: +jpgreqbuf_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; } - break; case BUZIOC_QBUF_CAPT: { @@ -2541,7 +2479,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case BUZIOC_QBUF_PLAY: { @@ -2556,7 +2493,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case BUZIOC_SYNC: { @@ -2571,7 +2507,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case BUZIOC_G_STATUS: { @@ -2615,7 +2550,7 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) input = zr->card.input[zr->input].muxsel; decoder_command(zr, DECODER_SET_INPUT, &input); decoder_command(zr, DECODER_SET_NORM, &zr->norm); - gstat_unlock_and_return: +gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); if (!res) { @@ -2634,1599 +2569,1297 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; - - /* The new video4linux2 capture interface - much nicer than video4linux1, since - * it allows for integrating the JPEG capturing calls inside standard v4l2 - */ - - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr)); - memset(cap, 0, sizeof(*cap)); - strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1); - strncpy(cap->driver, "zoran", sizeof(cap->driver)-1); - snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", - pci_name(zr->pci_dev)); - cap->version = - KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION, - RELEASE_VERSION); - cap->capabilities = ZORAN_V4L2_VID_FLAGS; - - return 0; + default: + return -EINVAL; } - break; - - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *fmt = arg; - int index = fmt->index, num = -1, i, flag = 0, type = - fmt->type; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUM_FMT - index=%d\n", - ZR_DEVNAME(zr), fmt->index); +static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - flag = ZORAN_FORMAT_CAPTURE; - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - flag = ZORAN_FORMAT_PLAYBACK; - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - flag = ZORAN_FORMAT_OVERLAY; - break; - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_ENUM_FMT - unknown type %d\n", - ZR_DEVNAME(zr), fmt->type); - return -EINVAL; - } + memset(cap, 0, sizeof(*cap)); + strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1); + strncpy(cap->driver, "zoran", sizeof(cap->driver)-1); + snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", + pci_name(zr->pci_dev)); + cap->version = + KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION, + RELEASE_VERSION); + cap->capabilities = ZORAN_V4L2_VID_FLAGS; - for (i = 0; i < NUM_FORMATS; i++) { - if (zoran_formats[i].flags & flag) - num++; - if (num == fmt->index) - break; - } - if (fmt->index < 0 /* late, but not too late */ || - i == NUM_FORMATS) - return -EINVAL; + return 0; +} - memset(fmt, 0, sizeof(*fmt)); - fmt->index = index; - fmt->type = type; - strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); - fmt->pixelformat = zoran_formats[i].fourcc; - if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) - fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; +static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag) +{ + int num = -1, i; - return 0; + for (i = 0; i < NUM_FORMATS; i++) { + if (zoran_formats[i].flags & flag) + num++; + if (num == fmt->index) + break; } - break; - - case VIDIOC_G_FMT: - { - struct v4l2_format *fmt = arg; - int type = fmt->type; + if (fmt->index < 0 /* late, but not too late */ || i == NUM_FORMATS) + return -EINVAL; - dprintk(5, KERN_DEBUG "%s: VIDIOC_G_FMT\n", ZR_DEVNAME(zr)); + strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); + fmt->pixelformat = zoran_formats[i].fourcc; + if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) + fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; + return 0; +} - memset(fmt, 0, sizeof(*fmt)); - fmt->type = type; +static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh, + struct v4l2_fmtdesc *f) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_OVERLAY: + return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE); +} - mutex_lock(&zr->resource_lock); +static int zoran_enum_fmt_vid_out(struct file *file, void *__fh, + struct v4l2_fmtdesc *f) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - fmt->fmt.win.w.left = fh->overlay_settings.x; - fmt->fmt.win.w.top = fh->overlay_settings.y; - fmt->fmt.win.w.width = fh->overlay_settings.width; - fmt->fmt.win.w.height = - fh->overlay_settings.height; - if (fh->overlay_settings.width * 2 > - BUZ_MAX_HEIGHT) - fmt->fmt.win.field = V4L2_FIELD_INTERLACED; - else - fmt->fmt.win.field = V4L2_FIELD_TOP; + return zoran_enum_fmt(zr, f, ZORAN_FORMAT_PLAYBACK); +} - mutex_unlock(&zr->resource_lock); +static int zoran_enum_fmt_vid_overlay(struct file *file, void *__fh, + struct v4l2_fmtdesc *f) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - break; + return zoran_enum_fmt(zr, f, ZORAN_FORMAT_OVERLAY); +} - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - - mutex_lock(&zr->resource_lock); - - if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && - fh->map_mode == ZORAN_MAP_MODE_RAW) { - - fmt->fmt.pix.width = - fh->v4l_settings.width; - fmt->fmt.pix.height = - fh->v4l_settings.height; - fmt->fmt.pix.sizeimage = - fh->v4l_settings.bytesperline * - fh->v4l_settings.height; - fmt->fmt.pix.pixelformat = - fh->v4l_settings.format->fourcc; - fmt->fmt.pix.colorspace = - fh->v4l_settings.format->colorspace; - fmt->fmt.pix.bytesperline = - fh->v4l_settings.bytesperline; - if (BUZ_MAX_HEIGHT < - (fh->v4l_settings.height * 2)) - fmt->fmt.pix.field = - V4L2_FIELD_INTERLACED; - else - fmt->fmt.pix.field = - V4L2_FIELD_TOP; +static int zoran_g_fmt_vid_out(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - } else { + mutex_lock(&zr->resource_lock); - fmt->fmt.pix.width = - fh->jpg_settings.img_width / - fh->jpg_settings.HorDcm; - fmt->fmt.pix.height = - fh->jpg_settings.img_height / - (fh->jpg_settings.VerDcm * - fh->jpg_settings.TmpDcm); - fmt->fmt.pix.sizeimage = - zoran_v4l2_calc_bufsize(&fh-> - jpg_settings); - fmt->fmt.pix.pixelformat = - V4L2_PIX_FMT_MJPEG; - if (fh->jpg_settings.TmpDcm == 1) - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_SEQ_BT : - V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_TOP : - V4L2_FIELD_BOTTOM); - - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.colorspace = - V4L2_COLORSPACE_SMPTE170M; - } + fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm; + fmt->fmt.pix.height = fh->jpg_settings.img_height / + (fh->jpg_settings.VerDcm * fh->jpg_settings.TmpDcm); + fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&fh->jpg_settings); + fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; + if (fh->jpg_settings.TmpDcm == 1) + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_BT); + else + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - mutex_unlock(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); + return 0; +} - break; +static int zoran_g_fmt_vid_cap(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_G_FMT - unsupported type %d\n", - ZR_DEVNAME(zr), fmt->type); - return -EINVAL; - } - return 0; - } - break; + if (fh->map_mode != ZORAN_MAP_MODE_RAW) + return zoran_g_fmt_vid_out(file, fh, fmt); - case VIDIOC_S_FMT: - { - struct v4l2_format *fmt = arg; - int i, res = 0; - __le32 printformat; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_FMT - type=%d, ", - ZR_DEVNAME(zr), fmt->type); - - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - - dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n", - fmt->fmt.win.w.left, fmt->fmt.win.w.top, - fmt->fmt.win.w.width, - fmt->fmt.win.w.height, - fmt->fmt.win.clipcount, - fmt->fmt.win.bitmap); - mutex_lock(&zr->resource_lock); - res = - setup_window(file, fmt->fmt.win.w.left, - fmt->fmt.win.w.top, - fmt->fmt.win.w.width, - fmt->fmt.win.w.height, - (struct video_clip __user *) - fmt->fmt.win.clips, - fmt->fmt.win.clipcount, - fmt->fmt.win.bitmap); - mutex_unlock(&zr->resource_lock); - return res; - break; + mutex_lock(&zr->resource_lock); + fmt->fmt.pix.width = fh->v4l_settings.width; + fmt->fmt.pix.height = fh->v4l_settings.height; + fmt->fmt.pix.sizeimage = fh->v4l_settings.bytesperline * + fh->v4l_settings.height; + fmt->fmt.pix.pixelformat = fh->v4l_settings.format->fourcc; + fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace; + fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline; + if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) + fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; + else + fmt->fmt.pix.field = V4L2_FIELD_TOP; + mutex_unlock(&zr->resource_lock); + return 0; +} - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - - printformat = - __cpu_to_le32(fmt->fmt.pix.pixelformat); - dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n", - fmt->fmt.pix.width, fmt->fmt.pix.height, - fmt->fmt.pix.pixelformat, - (char *) &printformat); - - /* we can be requested to do JPEG/raw playback/capture */ - if (! - (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || - (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && - fmt->fmt.pix.pixelformat == - V4L2_PIX_FMT_MJPEG))) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - unknown type %d/0x%x(%4.4s) combination\n", - ZR_DEVNAME(zr), fmt->type, - fmt->fmt.pix.pixelformat, - (char *) &printformat); - return -EINVAL; - } +static int zoran_g_fmt_vid_overlay(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) { - mutex_lock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - settings = fh->jpg_settings; + fmt->fmt.win.w.left = fh->overlay_settings.x; + fmt->fmt.win.w.top = fh->overlay_settings.y; + fmt->fmt.win.w.width = fh->overlay_settings.width; + fmt->fmt.win.w.height = fh->overlay_settings.height; + if (fh->overlay_settings.width * 2 > BUZ_MAX_HEIGHT) + fmt->fmt.win.field = V4L2_FIELD_INTERLACED; + else + fmt->fmt.win.field = V4L2_FIELD_TOP; - if (fh->v4l_buffers.allocated || - fh->jpg_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - cannot change capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto sfmtjpg_unlock_and_return; - } + mutex_unlock(&zr->resource_lock); + return 0; +} - /* we actually need to set 'real' parameters now */ - if ((fmt->fmt.pix.height * 2) > - BUZ_MAX_HEIGHT) - settings.TmpDcm = 1; - else - settings.TmpDcm = 2; - settings.decimation = 0; - if (fmt->fmt.pix.height <= - fh->jpg_settings.img_height / 2) - settings.VerDcm = 2; - else - settings.VerDcm = 1; - if (fmt->fmt.pix.width <= - fh->jpg_settings.img_width / 4) - settings.HorDcm = 4; - else if (fmt->fmt.pix.width <= - fh->jpg_settings.img_width / 2) - settings.HorDcm = 2; - else - settings.HorDcm = 1; - if (settings.TmpDcm == 1) - settings.field_per_buff = 2; - else - settings.field_per_buff = 1; - - /* check */ - if ((res = - zoran_check_jpg_settings(zr, - &settings))) - goto sfmtjpg_unlock_and_return; - - /* it's ok, so set them */ - fh->jpg_settings = settings; - - /* tell the user what we actually did */ - fmt->fmt.pix.width = - settings.img_width / settings.HorDcm; - fmt->fmt.pix.height = - settings.img_height * 2 / - (settings.TmpDcm * settings.VerDcm); - if (settings.TmpDcm == 1) - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_SEQ_TB : - V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_TOP : - V4L2_FIELD_BOTTOM); - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh-> - jpg_settings); - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.sizeimage = - fh->jpg_buffers.buffer_size; - fmt->fmt.pix.colorspace = - V4L2_COLORSPACE_SMPTE170M; - - /* we hereby abuse this variable to show that - * we're gonna do mjpeg capture */ - fh->map_mode = - (fmt->type == - V4L2_BUF_TYPE_VIDEO_CAPTURE) ? - ZORAN_MAP_MODE_JPG_REC : - ZORAN_MAP_MODE_JPG_PLAY; - sfmtjpg_unlock_and_return: - mutex_unlock(&zr->resource_lock); - } else { - for (i = 0; i < NUM_FORMATS; i++) - if (fmt->fmt.pix.pixelformat == - zoran_formats[i].fourcc) - break; - if (i == NUM_FORMATS) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n", - ZR_DEVNAME(zr), - fmt->fmt.pix.pixelformat, - (char *) &printformat); - return -EINVAL; - } - mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || - (fh->v4l_buffers.allocated && - fh->v4l_buffers.active != - ZORAN_FREE)) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - cannot change capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto sfmtv4l_unlock_and_return; - } - if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) - fmt->fmt.pix.height = - BUZ_MAX_HEIGHT; - if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) - fmt->fmt.pix.width = BUZ_MAX_WIDTH; - - if ((res = - zoran_v4l_set_format(file, - fmt->fmt.pix. - width, - fmt->fmt.pix. - height, - &zoran_formats - [i]))) - goto sfmtv4l_unlock_and_return; - - /* tell the user the - * results/missing stuff */ - fmt->fmt.pix.bytesperline = - fh->v4l_settings.bytesperline; - fmt->fmt.pix.sizeimage = - fh->v4l_settings.height * - fh->v4l_settings.bytesperline; - fmt->fmt.pix.colorspace = - fh->v4l_settings.format->colorspace; - if (BUZ_MAX_HEIGHT < - (fh->v4l_settings.height * 2)) - fmt->fmt.pix.field = - V4L2_FIELD_INTERLACED; - else - fmt->fmt.pix.field = - V4L2_FIELD_TOP; - - fh->map_mode = ZORAN_MAP_MODE_RAW; - sfmtv4l_unlock_and_return: - mutex_unlock(&zr->resource_lock); - } +static int zoran_try_fmt_vid_overlay(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - break; + mutex_lock(&zr->resource_lock); - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - unsupported type %d\n", - ZR_DEVNAME(zr), fmt->type); - return -EINVAL; - } + if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH) + fmt->fmt.win.w.width = BUZ_MAX_WIDTH; + if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH) + fmt->fmt.win.w.width = BUZ_MIN_WIDTH; + if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT) + fmt->fmt.win.w.height = BUZ_MAX_HEIGHT; + if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT) + fmt->fmt.win.w.height = BUZ_MIN_HEIGHT; - return res; - } - break; + mutex_unlock(&zr->resource_lock); + return 0; +} - case VIDIOC_G_FBUF: - { - struct v4l2_framebuffer *fb = arg; +static int zoran_try_fmt_vid_out(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + struct zoran_jpg_settings settings; + int res = 0; - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_FBUF\n", ZR_DEVNAME(zr)); + if (fmt->fmt.pix.bytesperline > 0) + return -EINVAL; - memset(fb, 0, sizeof(*fb)); - mutex_lock(&zr->resource_lock); - fb->base = zr->buffer.base; - fb->fmt.width = zr->buffer.width; - fb->fmt.height = zr->buffer.height; - if (zr->overlay_settings.format) { - fb->fmt.pixelformat = - fh->overlay_settings.format->fourcc; - } - fb->fmt.bytesperline = zr->buffer.bytesperline; - mutex_unlock(&zr->resource_lock); - fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; - fb->fmt.field = V4L2_FIELD_INTERLACED; - fb->flags = V4L2_FBUF_FLAG_OVERLAY; - fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; + if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) + return -EINVAL; - return 0; - } - break; + mutex_lock(&zr->resource_lock); + settings = fh->jpg_settings; - case VIDIOC_S_FBUF: - { - int i, res = 0; - struct v4l2_framebuffer *fb = arg; - __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat); + /* we actually need to set 'real' parameters now */ + if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT) + settings.TmpDcm = 1; + else + settings.TmpDcm = 2; + settings.decimation = 0; + if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2) + settings.VerDcm = 2; + else + settings.VerDcm = 1; + if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4) + settings.HorDcm = 4; + else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2) + settings.HorDcm = 2; + else + settings.HorDcm = 1; + if (settings.TmpDcm == 1) + settings.field_per_buff = 2; + else + settings.field_per_buff = 1; + + /* check */ + res = zoran_check_jpg_settings(zr, &settings); + if (res) + goto tryfmt_unlock_and_return; + + /* tell the user what we actually did */ + fmt->fmt.pix.width = settings.img_width / settings.HorDcm; + fmt->fmt.pix.height = settings.img_height * 2 / + (settings.TmpDcm * settings.VerDcm); + if (settings.TmpDcm == 1) + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); + else + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); - dprintk(3, - KERN_DEBUG - "%s: VIDIOC_S_FBUF - base=0x%p, size=%dx%d, bpl=%d, fmt=0x%x (%4.4s)\n", - ZR_DEVNAME(zr), fb->base, fb->fmt.width, fb->fmt.height, - fb->fmt.bytesperline, fb->fmt.pixelformat, - (char *) &printformat); + fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings); +tryfmt_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - for (i = 0; i < NUM_FORMATS; i++) - if (zoran_formats[i].fourcc == fb->fmt.pixelformat) - break; - if (i == NUM_FORMATS) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n", - ZR_DEVNAME(zr), fb->fmt.pixelformat, - (char *) &printformat); - return -EINVAL; - } +static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i; - mutex_lock(&zr->resource_lock); - res = - setup_fbuffer(file, fb->base, &zoran_formats[i], - fb->fmt.width, fb->fmt.height, - fb->fmt.bytesperline); - mutex_unlock(&zr->resource_lock); + if (fmt->fmt.pix.bytesperline > 0) + return -EINVAL; - return res; - } - break; + if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) + return zoran_try_fmt_vid_out(file, fh, fmt); - case VIDIOC_OVERLAY: - { - int *on = arg, res; + mutex_lock(&zr->resource_lock); - dprintk(3, KERN_DEBUG "%s: VIDIOC_PREVIEW - on=%d\n", - ZR_DEVNAME(zr), *on); + for (i = 0; i < NUM_FORMATS; i++) + if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat) + break; - mutex_lock(&zr->resource_lock); - res = setup_overlay(file, *on); + if (i == NUM_FORMATS) { mutex_unlock(&zr->resource_lock); - - return res; + return -EINVAL; } - break; - - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *req = arg; - int res = 0; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_REQBUFS - type=%d\n", - ZR_DEVNAME(zr), req->type); - if (req->memory != V4L2_MEMORY_MMAP) { - dprintk(1, - KERN_ERR - "%s: only MEMORY_MMAP capture is supported, not %d\n", - ZR_DEVNAME(zr), req->memory); - return -EINVAL; - } + if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) + fmt->fmt.pix.width = BUZ_MAX_WIDTH; + if (fmt->fmt.pix.width < BUZ_MIN_WIDTH) + fmt->fmt.pix.width = BUZ_MIN_WIDTH; + if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) + fmt->fmt.pix.height = BUZ_MAX_HEIGHT; + if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT) + fmt->fmt.pix.height = BUZ_MIN_HEIGHT; + mutex_unlock(&zr->resource_lock); - mutex_lock(&zr->resource_lock); + return 0; +} - if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_REQBUFS - buffers allready allocated\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto v4l2reqbuf_unlock_and_return; - } +static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res; + + dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n", + fmt->fmt.win.w.left, fmt->fmt.win.w.top, + fmt->fmt.win.w.width, + fmt->fmt.win.w.height, + fmt->fmt.win.clipcount, + fmt->fmt.win.bitmap); + mutex_lock(&zr->resource_lock); + res = setup_window(file, fmt->fmt.win.w.left, + fmt->fmt.win.w.top, + fmt->fmt.win.w.width, + fmt->fmt.win.w.height, + (struct video_clip __user *) + fmt->fmt.win.clips, + fmt->fmt.win.clipcount, + fmt->fmt.win.bitmap); + mutex_unlock(&zr->resource_lock); + return res; +} - if (fh->map_mode == ZORAN_MAP_MODE_RAW && - req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { +static int zoran_s_fmt_vid_out(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + __le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat); + struct zoran_jpg_settings settings; + int res = 0; - /* control user input */ - if (req->count < 2) - req->count = 2; - if (req->count > v4l_nbufs) - req->count = v4l_nbufs; - fh->v4l_buffers.num_buffers = req->count; + dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n", + fmt->fmt.pix.width, fmt->fmt.pix.height, + fmt->fmt.pix.pixelformat, + (char *) &printformat); + if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) + return -EINVAL; - if (v4l_fbuffer_alloc(file)) { - res = -ENOMEM; - goto v4l2reqbuf_unlock_and_return; - } + mutex_lock(&zr->resource_lock); - /* The next mmap will map the V4L buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; + settings = fh->jpg_settings; - } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC || - fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { + if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { + dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto sfmtjpg_unlock_and_return; + } - /* we need to calculate size ourselves now */ - if (req->count < 4) - req->count = 4; - if (req->count > jpg_nbufs) - req->count = jpg_nbufs; - fh->jpg_buffers.num_buffers = req->count; - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); - - if (jpg_fbuffer_alloc(file)) { - res = -ENOMEM; - goto v4l2reqbuf_unlock_and_return; - } - - /* The next mmap will map the MJPEG buffers */ - if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - fh->map_mode = ZORAN_MAP_MODE_JPG_REC; - else - fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY; - - } else { - dprintk(1, - KERN_ERR - "%s: VIDIOC_REQBUFS - unknown type %d\n", - ZR_DEVNAME(zr), req->type); - res = -EINVAL; - goto v4l2reqbuf_unlock_and_return; - } - v4l2reqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return 0; - } - break; - - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *buf = arg; - __u32 type = buf->type; - int index = buf->index, res; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOC_QUERYBUF - index=%d, type=%d\n", - ZR_DEVNAME(zr), buf->index, buf->type); + /* we actually need to set 'real' parameters now */ + if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT) + settings.TmpDcm = 1; + else + settings.TmpDcm = 2; + settings.decimation = 0; + if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2) + settings.VerDcm = 2; + else + settings.VerDcm = 1; + if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4) + settings.HorDcm = 4; + else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2) + settings.HorDcm = 2; + else + settings.HorDcm = 1; + if (settings.TmpDcm == 1) + settings.field_per_buff = 2; + else + settings.field_per_buff = 1; + + /* check */ + res = zoran_check_jpg_settings(zr, &settings); + if (res) + goto sfmtjpg_unlock_and_return; + + /* it's ok, so set them */ + fh->jpg_settings = settings; + + /* tell the user what we actually did */ + fmt->fmt.pix.width = settings.img_width / settings.HorDcm; + fmt->fmt.pix.height = settings.img_height * 2 / + (settings.TmpDcm * settings.VerDcm); + if (settings.TmpDcm == 1) + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); + else + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); + fh->jpg_buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.sizeimage = fh->jpg_buffers.buffer_size; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + + /* we hereby abuse this variable to show that + * we're gonna do mjpeg capture */ + fh->map_mode = (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? + ZORAN_MAP_MODE_JPG_REC : ZORAN_MAP_MODE_JPG_PLAY; +sfmtjpg_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - memset(buf, 0, sizeof(*buf)); - buf->type = type; - buf->index = index; +static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i; + int res = 0; - mutex_lock(&zr->resource_lock); - res = zoran_v4l2_buffer_status(file, buf, buf->index); - mutex_unlock(&zr->resource_lock); + if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) + return zoran_s_fmt_vid_out(file, fh, fmt); - return res; + for (i = 0; i < NUM_FORMATS; i++) + if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc) + break; + if (i == NUM_FORMATS) { + dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x\n", + ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat); + return -EINVAL; } - break; - - case VIDIOC_QBUF: - { - struct v4l2_buffer *buf = arg; - int res = 0, codec_mode, buf_type; - - dprintk(3, - KERN_DEBUG "%s: VIDIOC_QBUF - type=%d, index=%d\n", - ZR_DEVNAME(zr), buf->type, buf->index); + mutex_lock(&zr->resource_lock); + if (fh->jpg_buffers.allocated || + (fh->v4l_buffers.allocated && fh->v4l_buffers.active != ZORAN_FREE)) { + dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto sfmtv4l_unlock_and_return; + } + if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) + fmt->fmt.pix.height = BUZ_MAX_HEIGHT; + if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) + fmt->fmt.pix.width = BUZ_MAX_WIDTH; + + res = zoran_v4l_set_format(file, fmt->fmt.pix.width, + fmt->fmt.pix.height, &zoran_formats[i]); + if (res) + goto sfmtv4l_unlock_and_return; + + /* tell the user the + * results/missing stuff */ + fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline; + fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline; + fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace; + if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) + fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; + else + fmt->fmt.pix.field = V4L2_FIELD_TOP; - mutex_lock(&zr->resource_lock); + fh->map_mode = ZORAN_MAP_MODE_RAW; +sfmtv4l_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - goto qbuf_unlock_and_return; - } +static int zoran_g_fbuf(struct file *file, void *__fh, + struct v4l2_framebuffer *fb) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - res = zoran_v4l_queue_frame(file, buf->index); - if (res) - goto qbuf_unlock_and_return; - if (!zr->v4l_memgrab_active && - fh->v4l_buffers.active == ZORAN_LOCKED) - zr36057_set_memgrab(zr, 1); - break; + memset(fb, 0, sizeof(*fb)); + mutex_lock(&zr->resource_lock); + fb->base = zr->buffer.base; + fb->fmt.width = zr->buffer.width; + fb->fmt.height = zr->buffer.height; + if (zr->overlay_settings.format) + fb->fmt.pixelformat = fh->overlay_settings.format->fourcc; + fb->fmt.bytesperline = zr->buffer.bytesperline; + mutex_unlock(&zr->resource_lock); + fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; + fb->fmt.field = V4L2_FIELD_INTERLACED; + fb->flags = V4L2_FBUF_FLAG_OVERLAY; + fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { - buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - codec_mode = BUZ_MODE_MOTION_DECOMPRESS; - } else { - buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - codec_mode = BUZ_MODE_MOTION_COMPRESS; - } + return 0; +} - if (buf->type != buf_type) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - goto qbuf_unlock_and_return; - } +static int zoran_s_fbuf(struct file *file, void *__fh, + struct v4l2_framebuffer *fb) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i, res = 0; + __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat); - res = - zoran_jpg_queue_frame(file, buf->index, - codec_mode); - if (res != 0) - goto qbuf_unlock_and_return; - if (zr->codec_mode == BUZ_MODE_IDLE && - fh->jpg_buffers.active == ZORAN_LOCKED) { - zr36057_enable_jpg(zr, codec_mode); - } + for (i = 0; i < NUM_FORMATS; i++) + if (zoran_formats[i].fourcc == fb->fmt.pixelformat) break; - - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - unsupported type %d\n", - ZR_DEVNAME(zr), buf->type); - res = -EINVAL; - goto qbuf_unlock_and_return; - } - qbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; + if (i == NUM_FORMATS) { + dprintk(1, KERN_ERR "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n", + ZR_DEVNAME(zr), fb->fmt.pixelformat, + (char *)&printformat); + return -EINVAL; } - break; - - case VIDIOC_DQBUF: - { - struct v4l2_buffer *buf = arg; - int res = 0, buf_type, num = -1; /* compiler borks here (?) */ - dprintk(3, KERN_DEBUG "%s: VIDIOC_DQBUF - type=%d\n", - ZR_DEVNAME(zr), buf->type); - - mutex_lock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); + res = setup_fbuffer(file, fb->base, &zoran_formats[i], + fb->fmt.width, fb->fmt.height, + fb->fmt.bytesperline); + mutex_unlock(&zr->resource_lock); - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - goto dqbuf_unlock_and_return; - } + return res; +} - num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME]; - if (file->f_flags & O_NONBLOCK && - zr->v4l_buffers.buffer[num].state != - BUZ_STATE_DONE) { - res = -EAGAIN; - goto dqbuf_unlock_and_return; - } - res = v4l_sync(file, num); - if (res) - goto dqbuf_unlock_and_return; - else - zr->v4l_sync_tail++; - res = zoran_v4l2_buffer_status(file, buf, num); - break; +static int zoran_overlay(struct file *file, void *__fh, unsigned int on) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res; - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - { - struct zoran_sync bs; + mutex_lock(&zr->resource_lock); + res = setup_overlay(file, on); + mutex_unlock(&zr->resource_lock); - if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) - buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - else - buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + return res; +} - if (buf->type != buf_type) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - goto dqbuf_unlock_and_return; - } +static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0; - num = - zr->jpg_pend[zr-> - jpg_que_tail & BUZ_MASK_FRAME]; + if (req->memory != V4L2_MEMORY_MMAP) { + dprintk(1, + KERN_ERR + "%s: only MEMORY_MMAP capture is supported, not %d\n", + ZR_DEVNAME(zr), req->memory); + return -EINVAL; + } - if (file->f_flags & O_NONBLOCK && - zr->jpg_buffers.buffer[num].state != - BUZ_STATE_DONE) { - res = -EAGAIN; - goto dqbuf_unlock_and_return; - } - res = jpg_sync(file, &bs); - if (res) - goto dqbuf_unlock_and_return; - res = - zoran_v4l2_buffer_status(file, buf, bs.frame); - break; - } + mutex_lock(&zr->resource_lock); - default: - dprintk(1, + if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { + dprintk(1, KERN_ERR - "%s: VIDIOC_DQBUF - unsupported type %d\n", - ZR_DEVNAME(zr), buf->type); - res = -EINVAL; - goto dqbuf_unlock_and_return; - } - dqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; + "%s: VIDIOC_REQBUFS - buffers allready allocated\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto v4l2reqbuf_unlock_and_return; } - break; - - case VIDIOC_STREAMON: - { - int res = 0; - dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMON\n", ZR_DEVNAME(zr)); + if (fh->map_mode == ZORAN_MAP_MODE_RAW && + req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - mutex_lock(&zr->resource_lock); + /* control user input */ + if (req->count < 2) + req->count = 2; + if (req->count > v4l_nbufs) + req->count = v4l_nbufs; + fh->v4l_buffers.num_buffers = req->count; - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: /* raw capture */ - if (zr->v4l_buffers.active != ZORAN_ACTIVE || - fh->v4l_buffers.active != ZORAN_ACTIVE) { - res = -EBUSY; - goto strmon_unlock_and_return; - } + if (v4l_fbuffer_alloc(file)) { + res = -ENOMEM; + goto v4l2reqbuf_unlock_and_return; + } - zr->v4l_buffers.active = fh->v4l_buffers.active = - ZORAN_LOCKED; - zr->v4l_settings = fh->v4l_settings; + /* The next mmap will map the V4L buffers */ + fh->map_mode = ZORAN_MAP_MODE_RAW; - zr->v4l_sync_tail = zr->v4l_pend_tail; - if (!zr->v4l_memgrab_active && - zr->v4l_pend_head != zr->v4l_pend_tail) { - zr36057_set_memgrab(zr, 1); - } - break; + } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC || + fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - /* what is the codec mode right now? */ - if (zr->jpg_buffers.active != ZORAN_ACTIVE || - fh->jpg_buffers.active != ZORAN_ACTIVE) { - res = -EBUSY; - goto strmon_unlock_and_return; - } + /* we need to calculate size ourselves now */ + if (req->count < 4) + req->count = 4; + if (req->count > jpg_nbufs) + req->count = jpg_nbufs; + fh->jpg_buffers.num_buffers = req->count; + fh->jpg_buffers.buffer_size = + zoran_v4l2_calc_bufsize(&fh->jpg_settings); - zr->jpg_buffers.active = fh->jpg_buffers.active = - ZORAN_LOCKED; + if (jpg_fbuffer_alloc(file)) { + res = -ENOMEM; + goto v4l2reqbuf_unlock_and_return; + } - if (zr->jpg_que_head != zr->jpg_que_tail) { - /* Start the jpeg codec when the first frame is queued */ - jpeg_start(zr); - } + /* The next mmap will map the MJPEG buffers */ + if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + fh->map_mode = ZORAN_MAP_MODE_JPG_REC; + else + fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY; - break; - default: - dprintk(1, + } else { + dprintk(1, KERN_ERR - "%s: VIDIOC_STREAMON - invalid map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); - res = -EINVAL; - goto strmon_unlock_and_return; - } - strmon_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; + "%s: VIDIOC_REQBUFS - unknown type %d\n", + ZR_DEVNAME(zr), req->type); + res = -EINVAL; + goto v4l2reqbuf_unlock_and_return; } - break; - - case VIDIOC_STREAMOFF: - { - int i, res = 0; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMOFF\n", ZR_DEVNAME(zr)); - - mutex_lock(&zr->resource_lock); +v4l2reqbuf_unlock_and_return: + mutex_unlock(&zr->resource_lock); - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: /* raw capture */ - if (fh->v4l_buffers.active == ZORAN_FREE && - zr->v4l_buffers.active != ZORAN_FREE) { - res = -EPERM; /* stay off other's settings! */ - goto strmoff_unlock_and_return; - } - if (zr->v4l_buffers.active == ZORAN_FREE) - goto strmoff_unlock_and_return; + return res; +} - /* unload capture */ - if (zr->v4l_memgrab_active) { - unsigned long flags; +static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + __u32 type = buf->type; + int index = buf->index, res; - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - spin_unlock_irqrestore(&zr->spinlock, flags); - } + memset(buf, 0, sizeof(*buf)); + buf->type = type; + buf->index = index; - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) - zr->v4l_buffers.buffer[i].state = - BUZ_STATE_USER; - fh->v4l_buffers = zr->v4l_buffers; + mutex_lock(&zr->resource_lock); + res = zoran_v4l2_buffer_status(file, buf, buf->index); + mutex_unlock(&zr->resource_lock); - zr->v4l_buffers.active = fh->v4l_buffers.active = - ZORAN_FREE; + return res; +} - zr->v4l_grab_seq = 0; - zr->v4l_pend_head = zr->v4l_pend_tail = 0; - zr->v4l_sync_tail = 0; +static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0, codec_mode, buf_type; - break; + mutex_lock(&zr->resource_lock); - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->jpg_buffers.active == ZORAN_FREE && - zr->jpg_buffers.active != ZORAN_FREE) { - res = -EPERM; /* stay off other's settings! */ - goto strmoff_unlock_and_return; - } - if (zr->jpg_buffers.active == ZORAN_FREE) - goto strmoff_unlock_and_return; - - res = - jpg_qbuf(file, -1, - (fh->map_mode == - ZORAN_MAP_MODE_JPG_REC) ? - BUZ_MODE_MOTION_COMPRESS : - BUZ_MODE_MOTION_DECOMPRESS); - if (res) - goto strmoff_unlock_and_return; - break; - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_STREAMOFF - invalid map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); + switch (fh->map_mode) { + case ZORAN_MAP_MODE_RAW: + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", + ZR_DEVNAME(zr), buf->type, fh->map_mode); res = -EINVAL; - goto strmoff_unlock_and_return; + goto qbuf_unlock_and_return; } - strmoff_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; - } + res = zoran_v4l_queue_frame(file, buf->index); + if (res) + goto qbuf_unlock_and_return; + if (!zr->v4l_memgrab_active && + fh->v4l_buffers.active == ZORAN_LOCKED) + zr36057_set_memgrab(zr, 1); break; - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCTRL - id=%d\n", - ZR_DEVNAME(zr), ctrl->id); - - /* we only support hue/saturation/contrast/brightness */ - if (ctrl->id < V4L2_CID_BRIGHTNESS || - ctrl->id > V4L2_CID_HUE) - return -EINVAL; - else { - int id = ctrl->id; - memset(ctrl, 0, sizeof(*ctrl)); - ctrl->id = id; + case ZORAN_MAP_MODE_JPG_REC: + case ZORAN_MAP_MODE_JPG_PLAY: + if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { + buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + codec_mode = BUZ_MODE_MOTION_DECOMPRESS; + } else { + buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + codec_mode = BUZ_MODE_MOTION_COMPRESS; } - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1); - break; - case V4L2_CID_CONTRAST: - strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1); - break; - case V4L2_CID_SATURATION: - strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1); - break; - case V4L2_CID_HUE: - strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1); - break; + if (buf->type != buf_type) { + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", + ZR_DEVNAME(zr), buf->type, fh->map_mode); + res = -EINVAL; + goto qbuf_unlock_and_return; } - ctrl->minimum = 0; - ctrl->maximum = 65535; - ctrl->step = 1; - ctrl->default_value = 32768; - ctrl->type = V4L2_CTRL_TYPE_INTEGER; - - return 0; - } - break; - - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_CTRL - id=%d\n", - ZR_DEVNAME(zr), ctrl->id); - - /* we only support hue/saturation/contrast/brightness */ - if (ctrl->id < V4L2_CID_BRIGHTNESS || - ctrl->id > V4L2_CID_HUE) - return -EINVAL; - - mutex_lock(&zr->resource_lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = zr->brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = zr->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = zr->saturation; - break; - case V4L2_CID_HUE: - ctrl->value = zr->hue; - break; + res = zoran_jpg_queue_frame(file, buf->index, + codec_mode); + if (res != 0) + goto qbuf_unlock_and_return; + if (zr->codec_mode == BUZ_MODE_IDLE && + fh->jpg_buffers.active == ZORAN_LOCKED) { + zr36057_enable_jpg(zr, codec_mode); } - mutex_unlock(&zr->resource_lock); + break; - return 0; - } + default: + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - unsupported type %d\n", + ZR_DEVNAME(zr), buf->type); + res = -EINVAL; break; + } +qbuf_unlock_and_return: + mutex_unlock(&zr->resource_lock); - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - struct video_picture pict; + return res; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_CTRL - id=%d\n", - ZR_DEVNAME(zr), ctrl->id); +static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0, buf_type, num = -1; /* compiler borks here (?) */ - /* we only support hue/saturation/contrast/brightness */ - if (ctrl->id < V4L2_CID_BRIGHTNESS || - ctrl->id > V4L2_CID_HUE) - return -EINVAL; + mutex_lock(&zr->resource_lock); - if (ctrl->value < 0 || ctrl->value > 65535) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n", - ZR_DEVNAME(zr), ctrl->value, ctrl->id); - return -EINVAL; + switch (fh->map_mode) { + case ZORAN_MAP_MODE_RAW: + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", + ZR_DEVNAME(zr), buf->type, fh->map_mode); + res = -EINVAL; + goto dqbuf_unlock_and_return; } - mutex_lock(&zr->resource_lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - zr->brightness = ctrl->value; - break; - case V4L2_CID_CONTRAST: - zr->contrast = ctrl->value; - break; - case V4L2_CID_SATURATION: - zr->saturation = ctrl->value; - break; - case V4L2_CID_HUE: - zr->hue = ctrl->value; - break; + num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME]; + if (file->f_flags & O_NONBLOCK && + zr->v4l_buffers.buffer[num].state != BUZ_STATE_DONE) { + res = -EAGAIN; + goto dqbuf_unlock_and_return; } - pict.brightness = zr->brightness; - pict.contrast = zr->contrast; - pict.colour = zr->saturation; - pict.hue = zr->hue; - - decoder_command(zr, DECODER_SET_PICTURE, &pict); - - mutex_unlock(&zr->resource_lock); - - return 0; - } + res = v4l_sync(file, num); + if (res) + goto dqbuf_unlock_and_return; + zr->v4l_sync_tail++; + res = zoran_v4l2_buffer_status(file, buf, num); break; - case VIDIOC_ENUMSTD: + case ZORAN_MAP_MODE_JPG_REC: + case ZORAN_MAP_MODE_JPG_PLAY: { - struct v4l2_standard *std = arg; + struct zoran_sync bs; - dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMSTD - index=%d\n", - ZR_DEVNAME(zr), std->index); + if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) + buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + else + buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (std->index < 0 || std->index >= (zr->card.norms + 1)) - return -EINVAL; - else { - int id = std->index; - memset(std, 0, sizeof(*std)); - std->index = id; + if (buf->type != buf_type) { + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", + ZR_DEVNAME(zr), buf->type, fh->map_mode); + res = -EINVAL; + goto dqbuf_unlock_and_return; } - if (std->index == zr->card.norms) { - /* if we have autodetect, ... */ - struct video_decoder_capability caps; - decoder_command(zr, DECODER_GET_CAPABILITIES, - &caps); - if (caps.flags & VIDEO_DECODER_AUTO) { - std->id = V4L2_STD_ALL; - strncpy(std->name, "Autodetect", sizeof(std->name)-1); - return 0; - } else - return -EINVAL; - } - switch (std->index) { - case 0: - std->id = V4L2_STD_PAL; - strncpy(std->name, "PAL", sizeof(std->name)-1); - std->frameperiod.numerator = 1; - std->frameperiod.denominator = 25; - std->framelines = zr->card.tvn[0]->Ht; - break; - case 1: - std->id = V4L2_STD_NTSC; - strncpy(std->name, "NTSC", sizeof(std->name)-1); - std->frameperiod.numerator = 1001; - std->frameperiod.denominator = 30000; - std->framelines = zr->card.tvn[1]->Ht; - break; - case 2: - std->id = V4L2_STD_SECAM; - strncpy(std->name, "SECAM", sizeof(std->name)-1); - std->frameperiod.numerator = 1; - std->frameperiod.denominator = 25; - std->framelines = zr->card.tvn[2]->Ht; - break; - } + num = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; - return 0; + if (file->f_flags & O_NONBLOCK && + zr->jpg_buffers.buffer[num].state != BUZ_STATE_DONE) { + res = -EAGAIN; + goto dqbuf_unlock_and_return; + } + res = jpg_sync(file, &bs); + if (res) + goto dqbuf_unlock_and_return; + res = zoran_v4l2_buffer_status(file, buf, bs.frame); + break; } + + default: + dprintk(1, KERN_ERR + "%s: VIDIOC_DQBUF - unsupported type %d\n", + ZR_DEVNAME(zr), buf->type); + res = -EINVAL; break; + } +dqbuf_unlock_and_return: + mutex_unlock(&zr->resource_lock); - case VIDIOC_G_STD: - { - v4l2_std_id *std = arg; - int norm; + return res; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_STD\n", ZR_DEVNAME(zr)); +static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0; - mutex_lock(&zr->resource_lock); - norm = zr->norm; - mutex_unlock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - switch (norm) { - case VIDEO_MODE_PAL: - *std = V4L2_STD_PAL; - break; - case VIDEO_MODE_NTSC: - *std = V4L2_STD_NTSC; - break; - case VIDEO_MODE_SECAM: - *std = V4L2_STD_SECAM; - break; + switch (fh->map_mode) { + case ZORAN_MAP_MODE_RAW: /* raw capture */ + if (zr->v4l_buffers.active != ZORAN_ACTIVE || + fh->v4l_buffers.active != ZORAN_ACTIVE) { + res = -EBUSY; + goto strmon_unlock_and_return; } - return 0; - } + zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_LOCKED; + zr->v4l_settings = fh->v4l_settings; + + zr->v4l_sync_tail = zr->v4l_pend_tail; + if (!zr->v4l_memgrab_active && + zr->v4l_pend_head != zr->v4l_pend_tail) { + zr36057_set_memgrab(zr, 1); + } break; - case VIDIOC_S_STD: - { - int norm = -1, res = 0; - v4l2_std_id *std = arg; + case ZORAN_MAP_MODE_JPG_REC: + case ZORAN_MAP_MODE_JPG_PLAY: + /* what is the codec mode right now? */ + if (zr->jpg_buffers.active != ZORAN_ACTIVE || + fh->jpg_buffers.active != ZORAN_ACTIVE) { + res = -EBUSY; + goto strmon_unlock_and_return; + } - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n", - ZR_DEVNAME(zr), (unsigned long long)*std); + zr->jpg_buffers.active = fh->jpg_buffers.active = ZORAN_LOCKED; - if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL)) - norm = VIDEO_MODE_PAL; - else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC)) - norm = VIDEO_MODE_NTSC; - else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM)) - norm = VIDEO_MODE_SECAM; - else if (*std == V4L2_STD_ALL) - norm = VIDEO_MODE_AUTO; - else { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_STD - invalid norm 0x%llx\n", - ZR_DEVNAME(zr), (unsigned long long)*std); - return -EINVAL; + if (zr->jpg_que_head != zr->jpg_que_tail) { + /* Start the jpeg codec when the first frame is queued */ + jpeg_start(zr); } + break; - mutex_lock(&zr->resource_lock); - if ((res = zoran_set_norm(zr, norm))) - goto sstd_unlock_and_return; - - res = wait_grab_pending(zr); - sstd_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; - } + default: + dprintk(1, + KERN_ERR + "%s: VIDIOC_STREAMON - invalid map mode %d\n", + ZR_DEVNAME(zr), fh->map_mode); + res = -EINVAL; break; + } +strmon_unlock_and_return: + mutex_unlock(&zr->resource_lock); - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *inp = arg; - int status; + return res; +} + +static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i, res = 0; - dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMINPUT - index=%d\n", - ZR_DEVNAME(zr), inp->index); + mutex_lock(&zr->resource_lock); - if (inp->index < 0 || inp->index >= zr->card.inputs) - return -EINVAL; - else { - int id = inp->index; - memset(inp, 0, sizeof(*inp)); - inp->index = id; + switch (fh->map_mode) { + case ZORAN_MAP_MODE_RAW: /* raw capture */ + if (fh->v4l_buffers.active == ZORAN_FREE && + zr->v4l_buffers.active != ZORAN_FREE) { + res = -EPERM; /* stay off other's settings! */ + goto strmoff_unlock_and_return; } + if (zr->v4l_buffers.active == ZORAN_FREE) + goto strmoff_unlock_and_return; - strncpy(inp->name, zr->card.input[inp->index].name, - sizeof(inp->name) - 1); - inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_ALL; - - /* Get status of video decoder */ - mutex_lock(&zr->resource_lock); - decoder_command(zr, DECODER_GET_STATUS, &status); - mutex_unlock(&zr->resource_lock); + /* unload capture */ + if (zr->v4l_memgrab_active) { + unsigned long flags; - if (!(status & DECODER_STATUS_GOOD)) { - inp->status |= V4L2_IN_ST_NO_POWER; - inp->status |= V4L2_IN_ST_NO_SIGNAL; + spin_lock_irqsave(&zr->spinlock, flags); + zr36057_set_memgrab(zr, 0); + spin_unlock_irqrestore(&zr->spinlock, flags); } - if (!(status & DECODER_STATUS_COLOR)) - inp->status |= V4L2_IN_ST_NO_COLOR; - return 0; - } - break; + for (i = 0; i < fh->v4l_buffers.num_buffers; i++) + zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER; + fh->v4l_buffers = zr->v4l_buffers; - case VIDIOC_G_INPUT: - { - int *input = arg; + zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_INPUT\n", ZR_DEVNAME(zr)); + zr->v4l_grab_seq = 0; + zr->v4l_pend_head = zr->v4l_pend_tail = 0; + zr->v4l_sync_tail = 0; - mutex_lock(&zr->resource_lock); - *input = zr->input; - mutex_unlock(&zr->resource_lock); + break; - return 0; - } + case ZORAN_MAP_MODE_JPG_REC: + case ZORAN_MAP_MODE_JPG_PLAY: + if (fh->jpg_buffers.active == ZORAN_FREE && + zr->jpg_buffers.active != ZORAN_FREE) { + res = -EPERM; /* stay off other's settings! */ + goto strmoff_unlock_and_return; + } + if (zr->jpg_buffers.active == ZORAN_FREE) + goto strmoff_unlock_and_return; + + res = jpg_qbuf(file, -1, + (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? + BUZ_MODE_MOTION_COMPRESS : + BUZ_MODE_MOTION_DECOMPRESS); + if (res) + goto strmoff_unlock_and_return; + break; + default: + dprintk(1, KERN_ERR + "%s: VIDIOC_STREAMOFF - invalid map mode %d\n", + ZR_DEVNAME(zr), fh->map_mode); + res = -EINVAL; break; + } +strmoff_unlock_and_return: + mutex_unlock(&zr->resource_lock); - case VIDIOC_S_INPUT: - { - int *input = arg, res = 0; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_INPUT - input=%d\n", - ZR_DEVNAME(zr), *input); - - mutex_lock(&zr->resource_lock); - if ((res = zoran_set_input(zr, *input))) - goto sinput_unlock_and_return; + return res; +} - /* Make sure the changes come into effect */ - res = wait_grab_pending(zr); - sinput_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; +static int zoran_queryctrl(struct file *file, void *__fh, + struct v4l2_queryctrl *ctrl) +{ + /* we only support hue/saturation/contrast/brightness */ + if (ctrl->id < V4L2_CID_BRIGHTNESS || + ctrl->id > V4L2_CID_HUE) + return -EINVAL; + else { + int id = ctrl->id; + memset(ctrl, 0, sizeof(*ctrl)); + ctrl->id = id; } + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1); + break; + case V4L2_CID_CONTRAST: + strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1); + break; + case V4L2_CID_SATURATION: + strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1); break; + case V4L2_CID_HUE: + strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1); + break; + } - case VIDIOC_ENUMOUTPUT: - { - struct v4l2_output *outp = arg; + ctrl->minimum = 0; + ctrl->maximum = 65535; + ctrl->step = 1; + ctrl->default_value = 32768; + ctrl->type = V4L2_CTRL_TYPE_INTEGER; - dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMOUTPUT - index=%d\n", - ZR_DEVNAME(zr), outp->index); + return 0; +} - if (outp->index != 0) - return -EINVAL; +static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - memset(outp, 0, sizeof(*outp)); - outp->index = 0; - outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; - strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); + /* we only support hue/saturation/contrast/brightness */ + if (ctrl->id < V4L2_CID_BRIGHTNESS || + ctrl->id > V4L2_CID_HUE) + return -EINVAL; - return 0; - } + mutex_lock(&zr->resource_lock); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = zr->brightness; break; + case V4L2_CID_CONTRAST: + ctrl->value = zr->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = zr->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = zr->hue; + break; + } + mutex_unlock(&zr->resource_lock); - case VIDIOC_G_OUTPUT: - { - int *output = arg; + return 0; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_OUTPUT\n", ZR_DEVNAME(zr)); +static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + struct video_picture pict; - *output = 0; + /* we only support hue/saturation/contrast/brightness */ + if (ctrl->id < V4L2_CID_BRIGHTNESS || + ctrl->id > V4L2_CID_HUE) + return -EINVAL; - return 0; + if (ctrl->value < 0 || ctrl->value > 65535) { + dprintk(1, KERN_ERR + "%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n", + ZR_DEVNAME(zr), ctrl->value, ctrl->id); + return -EINVAL; } + + mutex_lock(&zr->resource_lock); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + zr->brightness = ctrl->value; + break; + case V4L2_CID_CONTRAST: + zr->contrast = ctrl->value; break; + case V4L2_CID_SATURATION: + zr->saturation = ctrl->value; + break; + case V4L2_CID_HUE: + zr->hue = ctrl->value; + break; + } + pict.brightness = zr->brightness; + pict.contrast = zr->contrast; + pict.colour = zr->saturation; + pict.hue = zr->hue; - case VIDIOC_S_OUTPUT: - { - int *output = arg; + decoder_command(zr, DECODER_SET_PICTURE, &pict); - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_OUTPUT - output=%d\n", - ZR_DEVNAME(zr), *output); + mutex_unlock(&zr->resource_lock); - if (*output != 0) - return -EINVAL; + return 0; +} - return 0; - } +static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int norm; + + mutex_lock(&zr->resource_lock); + norm = zr->norm; + mutex_unlock(&zr->resource_lock); + + switch (norm) { + case VIDEO_MODE_PAL: + *std = V4L2_STD_PAL; break; + case VIDEO_MODE_NTSC: + *std = V4L2_STD_NTSC; + break; + case VIDEO_MODE_SECAM: + *std = V4L2_STD_SECAM; + break; + } - /* cropping (sub-frame capture) */ - case VIDIOC_CROPCAP: - { - struct v4l2_cropcap *cropcap = arg; - int type = cropcap->type, res = 0; + return 0; +} - dprintk(3, KERN_ERR "%s: VIDIOC_CROPCAP - type=%d\n", - ZR_DEVNAME(zr), cropcap->type); +static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int norm = -1, res = 0; + + if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL)) + norm = VIDEO_MODE_PAL; + else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC)) + norm = VIDEO_MODE_NTSC; + else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM)) + norm = VIDEO_MODE_SECAM; + else if (*std == V4L2_STD_ALL) + norm = VIDEO_MODE_AUTO; + else { + dprintk(1, KERN_ERR + "%s: VIDIOC_S_STD - invalid norm 0x%llx\n", + ZR_DEVNAME(zr), (unsigned long long)*std); + return -EINVAL; + } - memset(cropcap, 0, sizeof(*cropcap)); - cropcap->type = type; + mutex_lock(&zr->resource_lock); + res = zoran_set_norm(zr, norm); + if (res) + goto sstd_unlock_and_return; - mutex_lock(&zr->resource_lock); + res = wait_grab_pending(zr); +sstd_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - fh->map_mode == ZORAN_MAP_MODE_RAW)) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto cropcap_unlock_and_return; - } +static int zoran_enum_input(struct file *file, void *__fh, + struct v4l2_input *inp) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int status; - cropcap->bounds.top = cropcap->bounds.left = 0; - cropcap->bounds.width = BUZ_MAX_WIDTH; - cropcap->bounds.height = BUZ_MAX_HEIGHT; - cropcap->defrect.top = cropcap->defrect.left = 0; - cropcap->defrect.width = BUZ_MIN_WIDTH; - cropcap->defrect.height = BUZ_MIN_HEIGHT; - cropcap_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; + if (inp->index < 0 || inp->index >= zr->card.inputs) + return -EINVAL; + else { + int id = inp->index; + memset(inp, 0, sizeof(*inp)); + inp->index = id; } - break; - case VIDIOC_G_CROP: - { - struct v4l2_crop *crop = arg; - int type = crop->type, res = 0; + strncpy(inp->name, zr->card.input[inp->index].name, + sizeof(inp->name) - 1); + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_ALL; - dprintk(3, KERN_ERR "%s: VIDIOC_G_CROP - type=%d\n", - ZR_DEVNAME(zr), crop->type); + /* Get status of video decoder */ + mutex_lock(&zr->resource_lock); + decoder_command(zr, DECODER_GET_STATUS, &status); + mutex_unlock(&zr->resource_lock); - memset(crop, 0, sizeof(*crop)); - crop->type = type; + if (!(status & DECODER_STATUS_GOOD)) { + inp->status |= V4L2_IN_ST_NO_POWER; + inp->status |= V4L2_IN_ST_NO_SIGNAL; + } + if (!(status & DECODER_STATUS_COLOR)) + inp->status |= V4L2_IN_ST_NO_COLOR; - mutex_lock(&zr->resource_lock); + return 0; +} - if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - fh->map_mode == ZORAN_MAP_MODE_RAW)) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto gcrop_unlock_and_return; - } +static int zoran_g_input(struct file *file, void *__fh, unsigned int *input) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - crop->c.top = fh->jpg_settings.img_y; - crop->c.left = fh->jpg_settings.img_x; - crop->c.width = fh->jpg_settings.img_width; - crop->c.height = fh->jpg_settings.img_height; + mutex_lock(&zr->resource_lock); + *input = zr->input; + mutex_unlock(&zr->resource_lock); - gcrop_unlock_and_return: - mutex_unlock(&zr->resource_lock); + return 0; +} - return res; - } - break; +static int zoran_s_input(struct file *file, void *__fh, unsigned int input) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res; - case VIDIOC_S_CROP: - { - struct v4l2_crop *crop = arg; - int res = 0; + mutex_lock(&zr->resource_lock); + res = zoran_set_input(zr, input); + if (res) + goto sinput_unlock_and_return; - settings = fh->jpg_settings; + /* Make sure the changes come into effect */ + res = wait_grab_pending(zr); +sinput_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - dprintk(3, - KERN_ERR - "%s: VIDIOC_S_CROP - type=%d, x=%d,y=%d,w=%d,h=%d\n", - ZR_DEVNAME(zr), crop->type, crop->c.left, crop->c.top, - crop->c.width, crop->c.height); +static int zoran_enum_output(struct file *file, void *__fh, + struct v4l2_output *outp) +{ + if (outp->index != 0) + return -EINVAL; - mutex_lock(&zr->resource_lock); + memset(outp, 0, sizeof(*outp)); + outp->index = 0; + outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; + strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_CROP - cannot change settings while active\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto scrop_unlock_and_return; - } + return 0; +} - if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - fh->map_mode == ZORAN_MAP_MODE_RAW)) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto scrop_unlock_and_return; - } +static int zoran_g_output(struct file *file, void *__fh, unsigned int *output) +{ + *output = 0; + + return 0; +} - /* move into a form that we understand */ - settings.img_x = crop->c.left; - settings.img_y = crop->c.top; - settings.img_width = crop->c.width; - settings.img_height = crop->c.height; +static int zoran_s_output(struct file *file, void *__fh, unsigned int output) +{ + if (output != 0) + return -EINVAL; - /* check validity */ - if ((res = zoran_check_jpg_settings(zr, &settings))) - goto scrop_unlock_and_return; + return 0; +} - /* accept */ - fh->jpg_settings = settings; +/* cropping (sub-frame capture) */ +static int zoran_cropcap(struct file *file, void *__fh, + struct v4l2_cropcap *cropcap) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int type = cropcap->type, res = 0; - scrop_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; - } - break; + memset(cropcap, 0, sizeof(*cropcap)); + cropcap->type = type; - case VIDIOC_G_JPEGCOMP: - { - struct v4l2_jpegcompression *params = arg; + mutex_lock(&zr->resource_lock); - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_JPEGCOMP\n", + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + fh->map_mode == ZORAN_MAP_MODE_RAW)) { + dprintk(1, KERN_ERR + "%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n", ZR_DEVNAME(zr)); + res = -EINVAL; + goto cropcap_unlock_and_return; + } - memset(params, 0, sizeof(*params)); + cropcap->bounds.top = cropcap->bounds.left = 0; + cropcap->bounds.width = BUZ_MAX_WIDTH; + cropcap->bounds.height = BUZ_MAX_HEIGHT; + cropcap->defrect.top = cropcap->defrect.left = 0; + cropcap->defrect.width = BUZ_MIN_WIDTH; + cropcap->defrect.height = BUZ_MIN_HEIGHT; +cropcap_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - mutex_lock(&zr->resource_lock); +static int zoran_g_crop(struct file *file, void *__fh, struct v4l2_crop *crop) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int type = crop->type, res = 0; - params->quality = fh->jpg_settings.jpg_comp.quality; - params->APPn = fh->jpg_settings.jpg_comp.APPn; - memcpy(params->APP_data, - fh->jpg_settings.jpg_comp.APP_data, - fh->jpg_settings.jpg_comp.APP_len); - params->APP_len = fh->jpg_settings.jpg_comp.APP_len; - memcpy(params->COM_data, - fh->jpg_settings.jpg_comp.COM_data, - fh->jpg_settings.jpg_comp.COM_len); - params->COM_len = fh->jpg_settings.jpg_comp.COM_len; - params->jpeg_markers = - fh->jpg_settings.jpg_comp.jpeg_markers; + memset(crop, 0, sizeof(*crop)); + crop->type = type; - mutex_unlock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - return 0; + if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + fh->map_mode == ZORAN_MAP_MODE_RAW)) { + dprintk(1, + KERN_ERR + "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n", + ZR_DEVNAME(zr)); + res = -EINVAL; + goto gcrop_unlock_and_return; } - break; - - case VIDIOC_S_JPEGCOMP: - { - struct v4l2_jpegcompression *params = arg; - int res = 0; - settings = fh->jpg_settings; + crop->c.top = fh->jpg_settings.img_y; + crop->c.left = fh->jpg_settings.img_x; + crop->c.width = fh->jpg_settings.img_width; + crop->c.height = fh->jpg_settings.img_height; - dprintk(3, - KERN_DEBUG - "%s: VIDIOC_S_JPEGCOMP - quality=%d, APPN=%d, APP_len=%d, COM_len=%d\n", - ZR_DEVNAME(zr), params->quality, params->APPn, - params->APP_len, params->COM_len); +gcrop_unlock_and_return: + mutex_unlock(&zr->resource_lock); - settings.jpg_comp = *params; + return res; +} - mutex_lock(&zr->resource_lock); +static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0; + struct zoran_jpg_settings settings; - if (fh->v4l_buffers.active != ZORAN_FREE || - fh->jpg_buffers.active != ZORAN_FREE) { - dprintk(1, - KERN_WARNING - "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto sjpegc_unlock_and_return; - } + settings = fh->jpg_settings; - if ((res = zoran_check_jpg_settings(zr, &settings))) - goto sjpegc_unlock_and_return; - if (!fh->jpg_buffers.allocated) - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); - fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; - sjpegc_unlock_and_return: - mutex_unlock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - return 0; + if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + dprintk(1, KERN_ERR + "%s: VIDIOC_S_CROP - cannot change settings while active\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto scrop_unlock_and_return; } - break; - case VIDIOC_QUERYSTD: /* why is this useful? */ - { - v4l2_std_id *std = arg; + if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + fh->map_mode == ZORAN_MAP_MODE_RAW)) { + dprintk(1, KERN_ERR + "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n", + ZR_DEVNAME(zr)); + res = -EINVAL; + goto scrop_unlock_and_return; + } - dprintk(3, - KERN_DEBUG "%s: VIDIOC_QUERY_STD - std=0x%llx\n", - ZR_DEVNAME(zr), (unsigned long long)*std); + /* move into a form that we understand */ + settings.img_x = crop->c.left; + settings.img_y = crop->c.top; + settings.img_width = crop->c.width; + settings.img_height = crop->c.height; - if (*std == V4L2_STD_ALL || *std == V4L2_STD_NTSC || - *std == V4L2_STD_PAL || (*std == V4L2_STD_SECAM && - zr->card.norms == 3)) { - return 0; - } + /* check validity */ + res = zoran_check_jpg_settings(zr, &settings); + if (res) + goto scrop_unlock_and_return; - return -EINVAL; - } - break; + /* accept */ + fh->jpg_settings = settings; - case VIDIOC_TRY_FMT: - { - struct v4l2_format *fmt = arg; - int res = 0; +scrop_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_TRY_FMT - type=%d\n", - ZR_DEVNAME(zr), fmt->type); +static int zoran_g_jpegcomp(struct file *file, void *__fh, + struct v4l2_jpegcompression *params) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + memset(params, 0, sizeof(*params)); - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - mutex_lock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH) - fmt->fmt.win.w.width = BUZ_MAX_WIDTH; - if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH) - fmt->fmt.win.w.width = BUZ_MIN_WIDTH; - if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT) - fmt->fmt.win.w.height = BUZ_MAX_HEIGHT; - if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT) - fmt->fmt.win.w.height = BUZ_MIN_HEIGHT; + params->quality = fh->jpg_settings.jpg_comp.quality; + params->APPn = fh->jpg_settings.jpg_comp.APPn; + memcpy(params->APP_data, + fh->jpg_settings.jpg_comp.APP_data, + fh->jpg_settings.jpg_comp.APP_len); + params->APP_len = fh->jpg_settings.jpg_comp.APP_len; + memcpy(params->COM_data, + fh->jpg_settings.jpg_comp.COM_data, + fh->jpg_settings.jpg_comp.COM_len); + params->COM_len = fh->jpg_settings.jpg_comp.COM_len; + params->jpeg_markers = + fh->jpg_settings.jpg_comp.jpeg_markers; - mutex_unlock(&zr->resource_lock); - break; + mutex_unlock(&zr->resource_lock); - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (fmt->fmt.pix.bytesperline > 0) - return -EINVAL; + return 0; +} - mutex_lock(&zr->resource_lock); - - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) { - settings = fh->jpg_settings; - - /* we actually need to set 'real' parameters now */ - if ((fmt->fmt.pix.height * 2) > - BUZ_MAX_HEIGHT) - settings.TmpDcm = 1; - else - settings.TmpDcm = 2; - settings.decimation = 0; - if (fmt->fmt.pix.height <= - fh->jpg_settings.img_height / 2) - settings.VerDcm = 2; - else - settings.VerDcm = 1; - if (fmt->fmt.pix.width <= - fh->jpg_settings.img_width / 4) - settings.HorDcm = 4; - else if (fmt->fmt.pix.width <= - fh->jpg_settings.img_width / 2) - settings.HorDcm = 2; - else - settings.HorDcm = 1; - if (settings.TmpDcm == 1) - settings.field_per_buff = 2; - else - settings.field_per_buff = 1; - - /* check */ - if ((res = - zoran_check_jpg_settings(zr, - &settings))) - goto tryfmt_unlock_and_return; - - /* tell the user what we actually did */ - fmt->fmt.pix.width = - settings.img_width / settings.HorDcm; - fmt->fmt.pix.height = - settings.img_height * 2 / - (settings.TmpDcm * settings.VerDcm); - if (settings.TmpDcm == 1) - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_SEQ_TB : - V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_TOP : - V4L2_FIELD_BOTTOM); - - fmt->fmt.pix.sizeimage = - zoran_v4l2_calc_bufsize(&settings); - } else if (fmt->type == - V4L2_BUF_TYPE_VIDEO_CAPTURE) { - int i; - - for (i = 0; i < NUM_FORMATS; i++) - if (zoran_formats[i].fourcc == - fmt->fmt.pix.pixelformat) - break; - if (i == NUM_FORMATS) { - res = -EINVAL; - goto tryfmt_unlock_and_return; - } +static int zoran_s_jpegcomp(struct file *file, void *__fh, + struct v4l2_jpegcompression *params) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0; + struct zoran_jpg_settings settings; - if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) - fmt->fmt.pix.width = BUZ_MAX_WIDTH; - if (fmt->fmt.pix.width < BUZ_MIN_WIDTH) - fmt->fmt.pix.width = BUZ_MIN_WIDTH; - if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) - fmt->fmt.pix.height = - BUZ_MAX_HEIGHT; - if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT) - fmt->fmt.pix.height = - BUZ_MIN_HEIGHT; - } else { - res = -EINVAL; - goto tryfmt_unlock_and_return; - } - tryfmt_unlock_and_return: - mutex_unlock(&zr->resource_lock); + settings = fh->jpg_settings; - return res; - break; + settings.jpg_comp = *params; - default: - return -EINVAL; - } + mutex_lock(&zr->resource_lock); - return 0; + if (fh->v4l_buffers.active != ZORAN_FREE || + fh->jpg_buffers.active != ZORAN_FREE) { + dprintk(1, KERN_WARNING + "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto sjpegc_unlock_and_return; } - break; - default: - dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n", - ZR_DEVNAME(zr), cmd); - return -ENOIOCTLCMD; - break; + res = zoran_check_jpg_settings(zr, &settings); + if (res) + goto sjpegc_unlock_and_return; + if (!fh->jpg_buffers.allocated) + fh->jpg_buffers.buffer_size = + zoran_v4l2_calc_bufsize(&fh->jpg_settings); + fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; +sjpegc_unlock_and_return: + mutex_unlock(&zr->resource_lock); - } return 0; } - -static long -zoran_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) -{ - return video_usercopy(file, cmd, arg, zoran_do_ioctl); -} - static unsigned int zoran_poll (struct file *file, poll_table *wait) @@ -4365,10 +3998,7 @@ zoran_vm_close (struct vm_area_struct *vma) fh->jpg_buffers.active = ZORAN_FREE; } - //jpg_fbuffer_free(file); - fh->jpg_buffers.allocated = 0; - fh->jpg_buffers.ready_to_be_freed = 1; - + jpg_fbuffer_free(file); mutex_unlock(&zr->resource_lock); } @@ -4405,10 +4035,7 @@ zoran_vm_close (struct vm_area_struct *vma) ZORAN_FREE; spin_unlock_irqrestore(&zr->spinlock, flags); } - //v4l_fbuffer_free(file); - fh->v4l_buffers.allocated = 0; - fh->v4l_buffers.ready_to_be_freed = 1; - + v4l_fbuffer_free(file); mutex_unlock(&zr->resource_lock); } @@ -4647,11 +4274,53 @@ zoran_mmap (struct file *file, return 0; } +static const struct v4l2_ioctl_ops zoran_ioctl_ops = { + .vidioc_querycap = zoran_querycap, + .vidioc_cropcap = zoran_cropcap, + .vidioc_s_crop = zoran_s_crop, + .vidioc_g_crop = zoran_g_crop, + .vidioc_enum_input = zoran_enum_input, + .vidioc_g_input = zoran_g_input, + .vidioc_s_input = zoran_s_input, + .vidioc_enum_output = zoran_enum_output, + .vidioc_g_output = zoran_g_output, + .vidioc_s_output = zoran_s_output, + .vidioc_g_fbuf = zoran_g_fbuf, + .vidioc_s_fbuf = zoran_s_fbuf, + .vidioc_g_std = zoran_g_std, + .vidioc_s_std = zoran_s_std, + .vidioc_g_jpegcomp = zoran_g_jpegcomp, + .vidioc_s_jpegcomp = zoran_s_jpegcomp, + .vidioc_overlay = zoran_overlay, + .vidioc_reqbufs = zoran_reqbufs, + .vidioc_querybuf = zoran_querybuf, + .vidioc_qbuf = zoran_qbuf, + .vidioc_dqbuf = zoran_dqbuf, + .vidioc_streamon = zoran_streamon, + .vidioc_streamoff = zoran_streamoff, + .vidioc_enum_fmt_vid_cap = zoran_enum_fmt_vid_cap, + .vidioc_enum_fmt_vid_out = zoran_enum_fmt_vid_out, + .vidioc_enum_fmt_vid_overlay = zoran_enum_fmt_vid_overlay, + .vidioc_g_fmt_vid_cap = zoran_g_fmt_vid_cap, + .vidioc_g_fmt_vid_out = zoran_g_fmt_vid_out, + .vidioc_g_fmt_vid_overlay = zoran_g_fmt_vid_overlay, + .vidioc_s_fmt_vid_cap = zoran_s_fmt_vid_cap, + .vidioc_s_fmt_vid_out = zoran_s_fmt_vid_out, + .vidioc_s_fmt_vid_overlay = zoran_s_fmt_vid_overlay, + .vidioc_try_fmt_vid_cap = zoran_try_fmt_vid_cap, + .vidioc_try_fmt_vid_out = zoran_try_fmt_vid_out, + .vidioc_try_fmt_vid_overlay = zoran_try_fmt_vid_overlay, + .vidioc_queryctrl = zoran_queryctrl, + .vidioc_s_ctrl = zoran_s_ctrl, + .vidioc_g_ctrl = zoran_g_ctrl, + .vidioc_default = zoran_default, +}; + static const struct v4l2_file_operations zoran_fops = { .owner = THIS_MODULE, .open = zoran_open, .release = zoran_close, - .ioctl = zoran_ioctl, + .ioctl = video_ioctl2, .read = zoran_read, .write = zoran_write, .mmap = zoran_mmap, @@ -4661,7 +4330,9 @@ static const struct v4l2_file_operations zoran_fops = { struct video_device zoran_template __devinitdata = { .name = ZORAN_NAME, .fops = &zoran_fops, + .ioctl_ops = &zoran_ioctl_ops, .release = &zoran_vdev_release, + .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, .minor = -1 }; -- cgit v1.2.3 From d69e4a1d433220958c117d5e9a51638eaeb3e361 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:20:05 +0100 Subject: zoran: remove broken BIGPHYS_AREA and BUZ_HIMEM code, and allow for kmallocs > 128 kB From: Hans Verkuil Remove memory allocation madness. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran.h | 2 - linux/drivers/media/video/zoran/zoran_driver.c | 247 +++---------------------- 2 files changed, 28 insertions(+), 221 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran.h b/linux/drivers/media/video/zoran/zoran.h index 1bf540cb5..76668bda0 100644 --- a/linux/drivers/media/video/zoran/zoran.h +++ b/linux/drivers/media/video/zoran/zoran.h @@ -170,8 +170,6 @@ Private IOCTL to set up for displaying MJPEG #endif #define V4L_MASK_FRAME (V4L_MAX_FRAME - 1) -#define MAX_KMALLOC_MEM (128*1024) - #include "zr36057.h" enum card_type { diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index afbb18b89..5c8630647 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -192,16 +192,6 @@ const struct zoran_format zoran_formats[] = { }; #define NUM_FORMATS ARRAY_SIZE(zoran_formats) -// RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined -#if !defined(CONFIG_BIGPHYS_AREA) && !defined(BUZ_USE_HIMEM) -//#undef CONFIG_BIGPHYS_AREA -#define BUZ_USE_HIMEM -#endif - -#if defined(CONFIG_BIGPHYS_AREA) -# include -#endif - static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ module_param(lock_norm, int, 0644); MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); @@ -237,79 +227,8 @@ static void jpg_fbuffer_free(struct file *file); * Allocate the V4L grab buffers * * These have to be pysically contiguous. - * If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc - * else we try to allocate them with bigphysarea_alloc_pages - * if the bigphysarea patch is present in the kernel, - * else we try to use high memory (if the user has bootet - * Linux with the necessary memory left over). - */ - -#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA) -static unsigned long -get_high_mem (unsigned long size) -{ -/* - * Check if there is usable memory at the end of Linux memory - * of at least size. Return the physical address of this memory, - * return 0 on failure. - * - * The idea is from Alexandro Rubini's book "Linux device drivers". - * The driver from him which is downloadable from O'Reilly's - * web site misses the "virt_to_phys(high_memory)" part - * (and therefore doesn't work at all - at least with 2.2.x kernels). - * - * It should be unnecessary to mention that THIS IS DANGEROUS, - * if more than one driver at a time has the idea to use this memory!!!! */ - volatile unsigned char __iomem *mem; - unsigned char c; - unsigned long hi_mem_ph; - unsigned long i; - - /* Map the high memory to user space */ - - hi_mem_ph = virt_to_phys(high_memory); - - mem = ioremap(hi_mem_ph, size); - if (!mem) { - dprintk(1, - KERN_ERR "%s: get_high_mem() - ioremap failed\n", - ZORAN_NAME); - return 0; - } - - for (i = 0; i < size; i++) { - /* Check if it is memory */ - c = i & 0xff; - writeb(c, mem + i); - if (readb(mem + i) != c) - break; - c = 255 - c; - writeb(c, mem + i); - if (readb(mem + i) != c) - break; - writeb(0, mem + i); /* zero out memory */ - - /* give the kernel air to breath */ - if ((i & 0x3ffff) == 0x3ffff) - schedule(); - } - - iounmap(mem); - - if (i != size) { - dprintk(1, - KERN_ERR - "%s: get_high_mem() - requested %lu, avail %lu\n", - ZORAN_NAME, size, i); - return 0; - } - - return hi_mem_ph; -} -#endif - static int v4l_fbuffer_alloc (struct file *file) { @@ -317,132 +236,37 @@ v4l_fbuffer_alloc (struct file *file) struct zoran *zr = fh->zr; int i, off; unsigned char *mem; -#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA) - unsigned long pmem = 0; -#endif for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { if (fh->v4l_buffers.buffer[i].fbuffer) dprintk(2, KERN_WARNING - "%s: v4l_fbuffer_alloc() - buffer %d allready allocated!?\n", + "%s: v4l_fbuffer_alloc() - buffer %d already allocated!?\n", ZR_DEVNAME(zr), i); //udelay(20); - if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) { - /* Use kmalloc */ - - mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL); - if (!mem) { - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n", - ZR_DEVNAME(zr), i); - v4l_fbuffer_free(file); - return -ENOBUFS; - } - fh->v4l_buffers.buffer[i].fbuffer = mem; - fh->v4l_buffers.buffer[i].fbuffer_phys = - virt_to_phys(mem); - fh->v4l_buffers.buffer[i].fbuffer_bus = - virt_to_bus(mem); - for (off = 0; off < fh->v4l_buffers.buffer_size; - off += PAGE_SIZE) - SetPageReserved(MAP_NR(mem + off)); - dprintk(4, - KERN_INFO - "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%llx)\n", - ZR_DEVNAME(zr), i, (unsigned long) mem, - (unsigned long long)virt_to_bus(mem)); - } else { -#if defined(CONFIG_BIGPHYS_AREA) - /* Use bigphysarea_alloc_pages */ - - int n = - (fh->v4l_buffers.buffer_size + PAGE_SIZE - - 1) / PAGE_SIZE; - - mem = - (unsigned char *) bigphysarea_alloc_pages(n, 0, - GFP_KERNEL); - if (mem == 0) { - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - bigphysarea_alloc_pages for V4L buf %d failed\n", - ZR_DEVNAME(zr), i); - v4l_fbuffer_free(file); - return -ENOBUFS; - } - fh->v4l_buffers.buffer[i].fbuffer = mem; - fh->v4l_buffers.buffer[i].fbuffer_phys = - virt_to_phys(mem); - fh->v4l_buffers.buffer[i].fbuffer_bus = - virt_to_bus(mem); - dprintk(4, - KERN_INFO - "%s: Bigphysarea frame %d mem %p (bus: 0x%lx)\n", - ZR_DEVNAME(zr), i, mem, virt_to_bus(mem)); - - /* Zero out the allocated memory */ - memset(fh->v4l_buffers.buffer[i].fbuffer, 0, - fh->v4l_buffers.buffer_size); -#else -#if defined(BUZ_USE_HIMEM) - - /* Use high memory which has been left at boot time */ - - /* Ok., Ok. this is an evil hack - we make - * the assumption that physical addresses are - * the same as bus addresses (true at least - * for Intel processors). The whole method of - * obtaining and using this memory is not very - * nice - but I hope it saves some poor users - * from kernel hacking, which might have even - * more evil results */ - - if (i == 0) { - int size = - fh->v4l_buffers.num_buffers * - fh->v4l_buffers.buffer_size; - - pmem = get_high_mem(size); - if (pmem == 0) { - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - get_high_mem (size = %d KB) for V4L bufs failed\n", - ZR_DEVNAME(zr), size >> 10); - return -ENOBUFS; - } - fh->v4l_buffers.buffer[0].fbuffer = NULL; - fh->v4l_buffers.buffer[0].fbuffer_phys = pmem; - fh->v4l_buffers.buffer[0].fbuffer_bus = pmem; - dprintk(4, - KERN_INFO - "%s: v4l_fbuffer_alloc() - using %d KB high memory\n", - ZR_DEVNAME(zr), size >> 10); - } else { - fh->v4l_buffers.buffer[i].fbuffer = NULL; - fh->v4l_buffers.buffer[i].fbuffer_phys = - pmem + i * fh->v4l_buffers.buffer_size; - fh->v4l_buffers.buffer[i].fbuffer_bus = - pmem + i * fh->v4l_buffers.buffer_size; - } -#else - /* No bigphysarea present, usage of high memory disabled, - * but user wants buffers of more than MAX_KMALLOC_MEM */ + mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL); + if (!mem) { dprintk(1, KERN_ERR - "%s: v4l_fbuffer_alloc() - no bigphysarea_patch present, usage of high memory disabled,\n", - ZR_DEVNAME(zr)); - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - sorry, could not allocate %d V4L buffers of size %d KB.\n", - ZR_DEVNAME(zr), fh->v4l_buffers.num_buffers, - fh->v4l_buffers.buffer_size >> 10); + "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n", + ZR_DEVNAME(zr), i); + v4l_fbuffer_free(file); return -ENOBUFS; -#endif -#endif } + fh->v4l_buffers.buffer[i].fbuffer = mem; + fh->v4l_buffers.buffer[i].fbuffer_phys = + virt_to_phys(mem); + fh->v4l_buffers.buffer[i].fbuffer_bus = + virt_to_bus(mem); + for (off = 0; off < fh->v4l_buffers.buffer_size; + off += PAGE_SIZE) + SetPageReserved(MAP_NR(mem + off)); + dprintk(4, + KERN_INFO + "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", + ZR_DEVNAME(zr), i, (unsigned long) mem, + virt_to_bus(mem)); } fh->v4l_buffers.allocated = 1; @@ -465,18 +289,11 @@ v4l_fbuffer_free (struct file *file) if (!fh->v4l_buffers.buffer[i].fbuffer) continue; - if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) { - mem = fh->v4l_buffers.buffer[i].fbuffer; - for (off = 0; off < fh->v4l_buffers.buffer_size; - off += PAGE_SIZE) - ClearPageReserved(MAP_NR(mem + off)); - kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); - } -#if defined(CONFIG_BIGPHYS_AREA) - else - bigphysarea_free_pages((void *) fh->v4l_buffers. - buffer[i].fbuffer); -#endif + mem = fh->v4l_buffers.buffer[i].fbuffer; + for (off = 0; off < fh->v4l_buffers.buffer_size; + off += PAGE_SIZE) + ClearPageReserved(MAP_NR(mem + off)); + kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); fh->v4l_buffers.buffer[i].fbuffer = NULL; } @@ -486,16 +303,10 @@ v4l_fbuffer_free (struct file *file) /* * Allocate the MJPEG grab buffers. * - * If the requested buffer size is smaller than MAX_KMALLOC_MEM, - * kmalloc is used to request a physically contiguous area, - * else we allocate the memory in framgents with get_zeroed_page. - * * If a Natoma chipset is present and this is a revision 1 zr36057, * each MJPEG buffer needs to be physically contiguous. * (RJ: This statement is from Dave Perks' original driver, * I could never check it because I have a zr36067) - * The driver cares about this because it reduces the buffer - * size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation). * * RJ: The contents grab buffers needs never be accessed in the driver. * Therefore there is no need to allocate them with vmalloc in order @@ -529,7 +340,7 @@ jpg_fbuffer_alloc (struct file *file) if (fh->jpg_buffers.buffer[i].frag_tab) dprintk(2, KERN_WARNING - "%s: jpg_fbuffer_alloc() - buffer %d allready allocated!?\n", + "%s: jpg_fbuffer_alloc() - buffer %d already allocated!?\n", ZR_DEVNAME(zr), i); /* Allocate fragment table for this buffer */ @@ -569,7 +380,7 @@ jpg_fbuffer_alloc (struct file *file) off += PAGE_SIZE) SetPageReserved(MAP_NR(mem + off)); } else { - /* jpg_bufsize is allreay page aligned */ + /* jpg_bufsize is already page aligned */ for (j = 0; j < fh->jpg_buffers.buffer_size / PAGE_SIZE; j++) { @@ -2238,6 +2049,7 @@ schan_unlock_and_return: return res; } + case VIDIOCGMBUF: { struct video_mbuf *vmbuf = arg; @@ -2434,16 +2246,13 @@ sparams_unlock_and_return: * tables to a Maximum of 2 MB */ if (breq->size > jpg_bufsize) breq->size = jpg_bufsize; - if (fh->jpg_buffers.need_contiguous && - breq->size > MAX_KMALLOC_MEM) - breq->size = MAX_KMALLOC_MEM; mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, KERN_ERR - "%s: BUZIOC_REQBUFS - buffers allready allocated\n", + "%s: BUZIOC_REQBUFS - buffers already allocated\n", ZR_DEVNAME(zr)); res = -EBUSY; goto jpgreqbuf_unlock_and_return; -- cgit v1.2.3 From c263f2e699cb58f1ac5e12e170d0879329845c0a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:23:24 +0100 Subject: zoran: use slider flag with volume etc. controls. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 5c8630647..ebae49f91 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -3261,6 +3261,7 @@ static int zoran_queryctrl(struct file *file, void *__fh, ctrl->step = 1; ctrl->default_value = 32768; ctrl->type = V4L2_CTRL_TYPE_INTEGER; + ctrl->flags = V4L2_CTRL_FLAG_SLIDER; return 0; } -- cgit v1.2.3 From a393861c10e72edfaf97362739be70ebe940c246 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:24:56 +0100 Subject: zoran: fix field typo. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index ebae49f91..eeb541f26 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2464,7 +2464,7 @@ static int zoran_g_fmt_vid_out(struct file *file, void *__fh, fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; if (fh->jpg_settings.TmpDcm == 1) fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? - V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_BT); + V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); else fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); -- cgit v1.2.3 From 0dd0437a3727766237df82bdfa89bc02a18cc901 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:28:28 +0100 Subject: zoran: set bytesperline to 0 when using MJPEG. From: Hans Verkuil Remove bogus check on bytesperline in the try_fmt_vid_out call. Just set it to 0. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index eeb541f26..b4a1b1c7b 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2550,12 +2550,11 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, struct zoran_jpg_settings settings; int res = 0; - if (fmt->fmt.pix.bytesperline > 0) - return -EINVAL; - if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) return -EINVAL; + fmt->fmt.pix.bytesperline = 0; + mutex_lock(&zr->resource_lock); settings = fh->jpg_settings; @@ -2609,9 +2608,6 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, struct zoran *zr = fh->zr; int i; - if (fmt->fmt.pix.bytesperline > 0) - return -EINVAL; - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) return zoran_try_fmt_vid_out(file, fh, fmt); -- cgit v1.2.3 From 4f77e897cb187126ad10aad97b2edc6a89395d79 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:51:13 +0100 Subject: zoran: remove old V4L1 ioctls, use v4l1-compat instead. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/Kconfig | 4 +- linux/drivers/media/video/zoran/zoran_driver.c | 459 +++---------------------- 2 files changed, 46 insertions(+), 417 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/Kconfig b/linux/drivers/media/video/zoran/Kconfig index 4ea5fa71d..a0fe52260 100644 --- a/linux/drivers/media/video/zoran/Kconfig +++ b/linux/drivers/media/video/zoran/Kconfig @@ -1,6 +1,6 @@ config VIDEO_ZORAN tristate "Zoran ZR36057/36067 Video For Linux" - depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS + depends on PCI && I2C_ALGOBIT && VIDEO_V4L2 && VIRT_TO_BUS help Say Y for support for MJPEG capture cards based on the Zoran 36057/36067 PCI controller chipset. This includes the Iomega @@ -66,7 +66,7 @@ config VIDEO_ZORAN_LML33R10 config VIDEO_ZORAN_AVS6EYES tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" - depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 + depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO help diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index b4a1b1c7b..6a2607998 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -614,64 +614,6 @@ zoran_v4l_queue_frame (struct file *file, return res; } -static int -v4l_grab (struct file *file, - struct video_mmap *mp) -{ - struct zoran_fh *fh = file->private_data; - struct zoran *zr = fh->zr; - int res = 0, i; - - for (i = 0; i < NUM_FORMATS; i++) { - if (zoran_formats[i].palette == mp->format && - zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE && - !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)) - break; - } - if (i == NUM_FORMATS || zoran_formats[i].depth == 0) { - dprintk(1, - KERN_ERR - "%s: v4l_grab() - wrong bytes-per-pixel format\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - /* - * To minimize the time spent in the IRQ routine, we avoid setting up - * the video front end there. - * If this grab has different parameters from a running streaming capture - * we stop the streaming capture and start it over again. - */ - if (zr->v4l_memgrab_active && - (zr->v4l_settings.width != mp->width || - zr->v4l_settings.height != mp->height || - zr->v4l_settings.format->palette != mp->format)) { - res = wait_grab_pending(zr); - if (res) - return res; - } - if ((res = zoran_v4l_set_format(file, - mp->width, - mp->height, - &zoran_formats[i]))) - return res; - zr->v4l_settings = fh->v4l_settings; - - /* queue the frame in the pending queue */ - if ((res = zoran_v4l_queue_frame(file, mp->frame))) { - fh->v4l_buffers.active = ZORAN_FREE; - return res; - } - - /* put the 36057 into frame grabbing mode */ - if (!res && !zr->v4l_memgrab_active) - zr36057_set_memgrab(zr, 1); - - //dprintk(4, KERN_INFO "%s: Frame grab 3...\n", ZR_DEVNAME(zr)); - - return res; -} - /* * Sync on a V4L buffer */ @@ -1761,6 +1703,7 @@ zoran_set_input (struct zoran *zr, * ioctl routine */ +#ifdef CONFIG_VIDEO_V4L1_COMPAT static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) { struct zoran_fh *fh = __fh; @@ -1768,363 +1711,6 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) struct zoran_jpg_settings settings; switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *vcap = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr)); - - memset(vcap, 0, sizeof(struct video_capability)); - strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1); - vcap->type = ZORAN_VID_TYPE; - - vcap->channels = zr->card.inputs; - vcap->audios = 0; - mutex_lock(&zr->resource_lock); - vcap->maxwidth = BUZ_MAX_WIDTH; - vcap->maxheight = BUZ_MAX_HEIGHT; - vcap->minwidth = BUZ_MIN_WIDTH; - vcap->minheight = BUZ_MIN_HEIGHT; - mutex_unlock(&zr->resource_lock); - - return 0; - } - - case VIDIOCGCHAN: - { - struct video_channel *vchan = arg; - int channel = vchan->channel; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGCHAN - channel=%d\n", - ZR_DEVNAME(zr), vchan->channel); - - memset(vchan, 0, sizeof(struct video_channel)); - if (channel > zr->card.inputs || channel < 0) { - dprintk(1, - KERN_ERR - "%s: VIDIOCGCHAN on not existing channel %d\n", - ZR_DEVNAME(zr), channel); - return -EINVAL; - } - - strcpy(vchan->name, zr->card.input[channel].name); - - vchan->tuners = 0; - vchan->flags = 0; - vchan->type = VIDEO_TYPE_CAMERA; - mutex_lock(&zr->resource_lock); - vchan->norm = zr->norm; - mutex_unlock(&zr->resource_lock); - vchan->channel = channel; - - return 0; - } - - /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says: - * - * * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input." - * * ^^^^^^^ - * * The famos BTTV driver has it implemented with a struct video_channel argument - * * and we follow it for compatibility reasons - * * - * * BTW: this is the only way the user can set the norm! - */ - - case VIDIOCSCHAN: - { - struct video_channel *vchan = arg; - int res; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCSCHAN - channel=%d, norm=%d\n", - ZR_DEVNAME(zr), vchan->channel, vchan->norm); - - mutex_lock(&zr->resource_lock); - if ((res = zoran_set_input(zr, vchan->channel))) - goto schan_unlock_and_return; - if ((res = zoran_set_norm(zr, vchan->norm))) - goto schan_unlock_and_return; - - /* Make sure the changes come into effect */ - res = wait_grab_pending(zr); -schan_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; - } - - case VIDIOCGPICT: - { - struct video_picture *vpict = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGPICT\n", ZR_DEVNAME(zr)); - - memset(vpict, 0, sizeof(struct video_picture)); - mutex_lock(&zr->resource_lock); - vpict->hue = zr->hue; - vpict->brightness = zr->brightness; - vpict->contrast = zr->contrast; - vpict->colour = zr->saturation; - if (fh->overlay_settings.format) { - vpict->depth = fh->overlay_settings.format->depth; - vpict->palette = fh->overlay_settings.format->palette; - } else { - vpict->depth = 0; - } - mutex_unlock(&zr->resource_lock); - - return 0; - } - - case VIDIOCSPICT: - { - struct video_picture *vpict = arg; - int i; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCSPICT - bri=%d, hue=%d, col=%d, con=%d, dep=%d, pal=%d\n", - ZR_DEVNAME(zr), vpict->brightness, vpict->hue, - vpict->colour, vpict->contrast, vpict->depth, - vpict->palette); - - for (i = 0; i < NUM_FORMATS; i++) { - const struct zoran_format *fmt = &zoran_formats[i]; - - if (fmt->palette != -1 && - fmt->flags & ZORAN_FORMAT_OVERLAY && - fmt->palette == vpict->palette && - fmt->depth == vpict->depth) - break; - } - if (i == NUM_FORMATS) { - dprintk(1, - KERN_ERR - "%s: VIDIOCSPICT - Invalid palette %d\n", - ZR_DEVNAME(zr), vpict->palette); - return -EINVAL; - } - - mutex_lock(&zr->resource_lock); - - decoder_command(zr, DECODER_SET_PICTURE, vpict); - - zr->hue = vpict->hue; - zr->contrast = vpict->contrast; - zr->saturation = vpict->colour; - zr->brightness = vpict->brightness; - - fh->overlay_settings.format = &zoran_formats[i]; - - mutex_unlock(&zr->resource_lock); - - return 0; - } - - case VIDIOCCAPTURE: - { - int *on = arg, res; - - dprintk(3, KERN_DEBUG "%s: VIDIOCCAPTURE - on=%d\n", - ZR_DEVNAME(zr), *on); - - mutex_lock(&zr->resource_lock); - res = setup_overlay(file, *on); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case VIDIOCGWIN: - { - struct video_window *vwin = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGWIN\n", ZR_DEVNAME(zr)); - - memset(vwin, 0, sizeof(struct video_window)); - mutex_lock(&zr->resource_lock); - vwin->x = fh->overlay_settings.x; - vwin->y = fh->overlay_settings.y; - vwin->width = fh->overlay_settings.width; - vwin->height = fh->overlay_settings.height; - mutex_unlock(&zr->resource_lock); - vwin->clipcount = 0; - return 0; - } - - case VIDIOCSWIN: - { - struct video_window *vwin = arg; - int res; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCSWIN - x=%d, y=%d, w=%d, h=%d, clipcount=%d\n", - ZR_DEVNAME(zr), vwin->x, vwin->y, vwin->width, - vwin->height, vwin->clipcount); - - mutex_lock(&zr->resource_lock); - res = - setup_window(file, vwin->x, vwin->y, vwin->width, - vwin->height, vwin->clips, - vwin->clipcount, NULL); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case VIDIOCGFBUF: - { - struct video_buffer *vbuf = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGFBUF\n", ZR_DEVNAME(zr)); - - mutex_lock(&zr->resource_lock); - *vbuf = zr->buffer; - mutex_unlock(&zr->resource_lock); - return 0; - } - - case VIDIOCSFBUF: - { - struct video_buffer *vbuf = arg; - int i, res = 0; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n", - ZR_DEVNAME(zr), vbuf->base, vbuf->width, - vbuf->height, vbuf->depth, vbuf->bytesperline); - - for (i = 0; i < NUM_FORMATS; i++) - if (zoran_formats[i].depth == vbuf->depth) - break; - if (i == NUM_FORMATS) { - dprintk(1, - KERN_ERR - "%s: VIDIOCSFBUF - invalid fbuf depth %d\n", - ZR_DEVNAME(zr), vbuf->depth); - return -EINVAL; - } - - mutex_lock(&zr->resource_lock); - res = - setup_fbuffer(file, vbuf->base, &zoran_formats[i], - vbuf->width, vbuf->height, - vbuf->bytesperline); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case VIDIOCSYNC: - { - int *frame = arg, res; - - dprintk(3, KERN_DEBUG "%s: VIDIOCSYNC - frame=%d\n", - ZR_DEVNAME(zr), *frame); - - mutex_lock(&zr->resource_lock); - res = v4l_sync(file, *frame); - mutex_unlock(&zr->resource_lock); - if (!res) - zr->v4l_sync_tail++; - return res; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap *vmap = arg; - int res; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCMCAPTURE - frame=%d, geom=%dx%d, fmt=%d\n", - ZR_DEVNAME(zr), vmap->frame, vmap->width, vmap->height, - vmap->format); - - mutex_lock(&zr->resource_lock); - res = v4l_grab(file, vmap); - mutex_unlock(&zr->resource_lock); - return res; - } - - - case VIDIOCGMBUF: - { - struct video_mbuf *vmbuf = arg; - int i, res = 0; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGMBUF\n", ZR_DEVNAME(zr)); - - vmbuf->size = - fh->v4l_buffers.num_buffers * - fh->v4l_buffers.buffer_size; - vmbuf->frames = fh->v4l_buffers.num_buffers; - for (i = 0; i < vmbuf->frames; i++) { - vmbuf->offsets[i] = - i * fh->v4l_buffers.buffer_size; - } - - mutex_lock(&zr->resource_lock); - - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOCGMBUF - buffers already allocated\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto v4l1reqbuf_unlock_and_return; - } - - if (v4l_fbuffer_alloc(file)) { - res = -ENOMEM; - goto v4l1reqbuf_unlock_and_return; - } - - /* The next mmap will map the V4L buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; -v4l1reqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; - } - - case VIDIOCGUNIT: - { - struct video_unit *vunit = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGUNIT\n", ZR_DEVNAME(zr)); - - vunit->video = zr->video_dev->minor; - vunit->vbi = VIDEO_NO_UNIT; - vunit->radio = VIDEO_NO_UNIT; - vunit->audio = VIDEO_NO_UNIT; - vunit->teletext = VIDEO_NO_UNIT; - - return 0; - } - - /* - * RJ: In principal we could support subcaptures for V4L grabbing. - * Not even the famous BTTV driver has them, however. - * If there should be a strong demand, one could consider - * to implement them. - */ - case VIDIOCGCAPTURE: - { - dprintk(3, KERN_ERR "%s: VIDIOCGCAPTURE not supported\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - case VIDIOCSCAPTURE: - { - dprintk(3, KERN_ERR "%s: VIDIOCSCAPTURE not supported\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - case BUZIOC_G_PARAMS: { struct zoran_params *bparams = arg; @@ -2384,6 +1970,46 @@ gstat_unlock_and_return: } } +static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *vmbuf) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i, res = 0; + + vmbuf->size = + fh->v4l_buffers.num_buffers * + fh->v4l_buffers.buffer_size; + vmbuf->frames = fh->v4l_buffers.num_buffers; + for (i = 0; i < vmbuf->frames; i++) { + vmbuf->offsets[i] = + i * fh->v4l_buffers.buffer_size; + } + + mutex_lock(&zr->resource_lock); + + if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + dprintk(1, + KERN_ERR + "%s: VIDIOCGMBUF - buffers already allocated\n", + ZR_DEVNAME(zr)); + res = -EINVAL; + goto v4l1reqbuf_unlock_and_return; + } + + if (v4l_fbuffer_alloc(file)) { + res = -ENOMEM; + goto v4l1reqbuf_unlock_and_return; + } + + /* The next mmap will map the V4L buffers */ + fh->map_mode = ZORAN_MAP_MODE_RAW; +v4l1reqbuf_unlock_and_return: + mutex_unlock(&zr->resource_lock); + + return res; +} +#endif + static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap) { struct zoran_fh *fh = __fh; @@ -4119,7 +3745,10 @@ static const struct v4l2_ioctl_ops zoran_ioctl_ops = { .vidioc_queryctrl = zoran_queryctrl, .vidioc_s_ctrl = zoran_s_ctrl, .vidioc_g_ctrl = zoran_g_ctrl, +#ifdef CONFIG_VIDEO_V4L1_COMPAT .vidioc_default = zoran_default, + .vidiocgmbuf = zoran_vidiocgmbuf, +#endif }; static const struct v4l2_file_operations zoran_fops = { -- cgit v1.2.3 From 7b62aa559970adaf22b84c7e776fbefc96d14dd1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:52:24 +0100 Subject: zoran: set correct parent of the video device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_card.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 5d0fa99f2..99a25218b 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1138,6 +1138,7 @@ zr36057_init (struct zoran *zr) * Now add the template and register the device unit. */ memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); + zr->video_dev->parent = &zr->pci_dev->dev; strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); if (err < 0) -- cgit v1.2.3 From f29dd75cad2ab933c187296919168a2a2a34ae1b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 21:00:37 +0100 Subject: zoran: cleanups in an attempt to make the source a bit more readable. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_card.c | 9 +- linux/drivers/media/video/zoran/zoran_device.c | 404 +++++++++++-------------- linux/drivers/media/video/zoran/zoran_driver.c | 4 +- 3 files changed, 184 insertions(+), 233 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 99a25218b..ef0533086 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -920,15 +920,12 @@ zoran_check_jpg_settings (struct zoran *zr, err0++; if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) err0++; - if (settings->img_y + settings->img_height > - BUZ_MAX_HEIGHT / 2) + if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) err0++; if (settings->HorDcm && settings->VerDcm) { - if (settings->img_width % - (16 * settings->HorDcm) != 0) + if (settings->img_width % (16 * settings->HorDcm) != 0) err0++; - if (settings->img_height % - (8 * settings->VerDcm) != 0) + if (settings->img_height % (8 * settings->VerDcm) != 0) err0++; } diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index 87f894fa2..592300e2f 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -1209,22 +1209,52 @@ zoran_reap_stat_com (struct zoran *zr) } } +static void zoran_restart(struct zoran *zr) +{ + /* Now the stat_comm buffer is ready for restart */ + int status, mode; + + if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { + decoder_command(zr, DECODER_GET_STATUS, &status); + mode = CODEC_DO_COMPRESSION; + } else { + status = 0; + mode = CODEC_DO_EXPANSION; + } + if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || + (status & DECODER_STATUS_GOOD)) { + /********** RESTART code *************/ + jpeg_codec_reset(zr); + zr->codec->set_mode(zr->codec, mode); + zr36057_set_jpg(zr, zr->codec_mode); + jpeg_start(zr); + + if (zr->num_errors <= 8) + dprintk(2, KERN_INFO "%s: Restart\n", + ZR_DEVNAME(zr)); + + zr->JPEG_missed = 0; + zr->JPEG_error = 2; + /********** End RESTART code ***********/ + } +} + static void error_handler (struct zoran *zr, u32 astat, u32 stat) { + int i, j; + /* This is JPEG error handling part */ - if ((zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) && - (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS)) { - //dprintk(1, KERN_ERR "%s: Internal error: error handling request in mode %d\n", ZR_DEVNAME(zr), zr->codec_mode); + if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS && + zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS) { return; } if ((stat & 1) == 0 && zr->codec_mode == BUZ_MODE_MOTION_COMPRESS && - zr->jpg_dma_tail - zr->jpg_que_tail >= - zr->jpg_buffers.num_buffers) { + zr->jpg_dma_tail - zr->jpg_que_tail >= zr->jpg_buffers.num_buffers) { /* No free buffers... */ zoran_reap_stat_com(zr); zoran_feed_stat_com(zr); @@ -1233,142 +1263,95 @@ error_handler (struct zoran *zr, return; } - if (zr->JPEG_error != 1) { - /* - * First entry: error just happened during normal operation - * - * In BUZ_MODE_MOTION_COMPRESS: - * - * Possible glitch in TV signal. In this case we should - * stop the codec and wait for good quality signal before - * restarting it to avoid further problems - * - * In BUZ_MODE_MOTION_DECOMPRESS: - * - * Bad JPEG frame: we have to mark it as processed (codec crashed - * and was not able to do it itself), and to remove it from queue. - */ - btand(~ZR36057_JMC_Go_en, ZR36057_JMC); - udelay(1); - stat = stat | (post_office_read(zr, 7, 0) & 3) << 8; - btwrite(0, ZR36057_JPC); - btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); - jpeg_codec_reset(zr); - jpeg_codec_sleep(zr, 1); - zr->JPEG_error = 1; - zr->num_errors++; - - /* Report error */ - if (zr36067_debug > 1 && zr->num_errors <= 8) { - long frame; - frame = - zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; - printk(KERN_ERR - "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ", - ZR_DEVNAME(zr), stat, zr->last_isr, - zr->jpg_que_tail, zr->jpg_dma_tail, - zr->jpg_dma_head, zr->jpg_que_head, - zr->jpg_seq_num, frame); - printk("stat_com frames:"); - { - int i, j; - for (j = 0; j < BUZ_NUM_STAT_COM; j++) { - for (i = 0; - i < zr->jpg_buffers.num_buffers; - i++) { - if (le32_to_cpu(zr->stat_com[j]) == - zr->jpg_buffers. - buffer[i]. - frag_tab_bus) { - printk("% d->%d", - j, i); - } - } - } - printk("\n"); - } - } - /* Find an entry in stat_com and rotate contents */ - { - int i; - - if (zr->jpg_settings.TmpDcm == 1) - i = (zr->jpg_dma_tail - - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; - else - i = ((zr->jpg_dma_tail - - zr->jpg_err_shift) & 1) * 2; - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) { - /* Mimic zr36067 operation */ - zr->stat_com[i] |= cpu_to_le32(1); - if (zr->jpg_settings.TmpDcm != 1) - zr->stat_com[i + 1] |= cpu_to_le32(1); - /* Refill */ - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - wake_up_interruptible(&zr->jpg_capq); - /* Find an entry in stat_com again after refill */ - if (zr->jpg_settings.TmpDcm == 1) - i = (zr->jpg_dma_tail - - zr->jpg_err_shift) & - BUZ_MASK_STAT_COM; - else - i = ((zr->jpg_dma_tail - - zr->jpg_err_shift) & 1) * 2; - } - if (i) { - /* Rotate stat_comm entries to make current entry first */ - int j; - __le32 bus_addr[BUZ_NUM_STAT_COM]; - - /* Here we are copying the stat_com array, which - * is already in little endian format, so - * no endian conversions here - */ - memcpy(bus_addr, zr->stat_com, - sizeof(bus_addr)); - for (j = 0; j < BUZ_NUM_STAT_COM; j++) { - zr->stat_com[j] = - bus_addr[(i + j) & - BUZ_MASK_STAT_COM]; + if (zr->JPEG_error == 1) { + zoran_restart(zr); + return; + } - } - zr->jpg_err_shift += i; - zr->jpg_err_shift &= BUZ_MASK_STAT_COM; + /* + * First entry: error just happened during normal operation + * + * In BUZ_MODE_MOTION_COMPRESS: + * + * Possible glitch in TV signal. In this case we should + * stop the codec and wait for good quality signal before + * restarting it to avoid further problems + * + * In BUZ_MODE_MOTION_DECOMPRESS: + * + * Bad JPEG frame: we have to mark it as processed (codec crashed + * and was not able to do it itself), and to remove it from queue. + */ + btand(~ZR36057_JMC_Go_en, ZR36057_JMC); + udelay(1); + stat = stat | (post_office_read(zr, 7, 0) & 3) << 8; + btwrite(0, ZR36057_JPC); + btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); + jpeg_codec_reset(zr); + jpeg_codec_sleep(zr, 1); + zr->JPEG_error = 1; + zr->num_errors++; + + /* Report error */ + if (zr36067_debug > 1 && zr->num_errors <= 8) { + long frame; + + frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; + printk(KERN_ERR + "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ", + ZR_DEVNAME(zr), stat, zr->last_isr, + zr->jpg_que_tail, zr->jpg_dma_tail, + zr->jpg_dma_head, zr->jpg_que_head, + zr->jpg_seq_num, frame); + printk(KERN_INFO "stat_com frames:"); + for (j = 0; j < BUZ_NUM_STAT_COM; j++) { + for (i = 0; i < zr->jpg_buffers.num_buffers; i++) { + if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].frag_tab_bus) + printk(KERN_CONT "% d->%d", j, i); } - if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) - zr->jpg_err_seq = zr->jpg_seq_num; /* + 1; */ } + printk(KERN_CONT "\n"); } + /* Find an entry in stat_com and rotate contents */ + if (zr->jpg_settings.TmpDcm == 1) + i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; + else + i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2; + if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) { + /* Mimic zr36067 operation */ + zr->stat_com[i] |= cpu_to_le32(1); + if (zr->jpg_settings.TmpDcm != 1) + zr->stat_com[i + 1] |= cpu_to_le32(1); + /* Refill */ + zoran_reap_stat_com(zr); + zoran_feed_stat_com(zr); + wake_up_interruptible(&zr->jpg_capq); + /* Find an entry in stat_com again after refill */ + if (zr->jpg_settings.TmpDcm == 1) + i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; + else + i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2; + } + if (i) { + /* Rotate stat_comm entries to make current entry first */ + int j; + __le32 bus_addr[BUZ_NUM_STAT_COM]; + + /* Here we are copying the stat_com array, which + * is already in little endian format, so + * no endian conversions here + */ + memcpy(bus_addr, zr->stat_com, sizeof(bus_addr)); - /* Now the stat_comm buffer is ready for restart */ - do { - int status, mode; - - if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - decoder_command(zr, DECODER_GET_STATUS, &status); - mode = CODEC_DO_COMPRESSION; - } else { - status = 0; - mode = CODEC_DO_EXPANSION; - } - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - (status & DECODER_STATUS_GOOD)) { - /********** RESTART code *************/ - jpeg_codec_reset(zr); - zr->codec->set_mode(zr->codec, mode); - zr36057_set_jpg(zr, zr->codec_mode); - jpeg_start(zr); - - if (zr->num_errors <= 8) - dprintk(2, KERN_INFO "%s: Restart\n", - ZR_DEVNAME(zr)); + for (j = 0; j < BUZ_NUM_STAT_COM; j++) + zr->stat_com[j] = bus_addr[(i + j) & BUZ_MASK_STAT_COM]; - zr->JPEG_missed = 0; - zr->JPEG_error = 2; - /********** End RESTART code ***********/ - } - } while (0); + zr->jpg_err_shift += i; + zr->jpg_err_shift &= BUZ_MASK_STAT_COM; + } + if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) + zr->jpg_err_seq = zr->jpg_seq_num; /* + 1; */ + zoran_restart(zr); } irqreturn_t @@ -1431,10 +1414,8 @@ zoran_irq (int irq, * We simply ignore them */ if (zr->v4l_memgrab_active) { - /* A lot more checks should be here ... */ - if ((btread(ZR36057_VSSFGR) & - ZR36057_VSSFGR_SnapShot) == 0) + if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0) dprintk(1, KERN_WARNING "%s: BuzIRQ with SnapShot off ???\n", @@ -1442,10 +1423,7 @@ zoran_irq (int irq, if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) { /* There is a grab on a frame going on, check if it has finished */ - - if ((btread(ZR36057_VSSFGR) & - ZR36057_VSSFGR_FrameGrab) == - 0) { + if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) { /* it is finished, notify the user */ zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE; @@ -1463,9 +1441,7 @@ zoran_irq (int irq, if (zr->v4l_grab_frame == NO_GRAB_ACTIVE && zr->v4l_pend_tail != zr->v4l_pend_head) { - - int frame = zr->v4l_pend[zr->v4l_pend_tail & - V4L_MASK_FRAME]; + int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; u32 reg; zr->v4l_grab_frame = frame; @@ -1474,27 +1450,17 @@ zoran_irq (int irq, /* Buffer address */ - reg = - zr->v4l_buffers.buffer[frame]. - fbuffer_bus; + reg = zr->v4l_buffers.buffer[frame].fbuffer_bus; btwrite(reg, ZR36057_VDTR); - if (zr->v4l_settings.height > - BUZ_MAX_HEIGHT / 2) - reg += - zr->v4l_settings. - bytesperline; + if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2) + reg += zr->v4l_settings.bytesperline; btwrite(reg, ZR36057_VDBR); /* video stride, status, and frame grab register */ reg = 0; - if (zr->v4l_settings.height > - BUZ_MAX_HEIGHT / 2) - reg += - zr->v4l_settings. - bytesperline; - reg = - (reg << - ZR36057_VSSFGR_DispStride); + if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2) + reg += zr->v4l_settings.bytesperline; + reg = (reg << ZR36057_VSSFGR_DispStride); reg |= ZR36057_VSSFGR_VidOvf; reg |= ZR36057_VSSFGR_SnapShot; reg |= ZR36057_VSSFGR_FrameGrab; @@ -1512,77 +1478,66 @@ zoran_irq (int irq, #if (IRQ_MASK & ZR36057_ISR_CodRepIRQ) if (astat & ZR36057_ISR_CodRepIRQ) { zr->intr_counter_CodRepIRQ++; - IDEBUG(printk - (KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n", + IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n", ZR_DEVNAME(zr))); btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR); } #endif /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */ #if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) - if (astat & ZR36057_ISR_JPEGRepIRQ) { - - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - if (zr36067_debug > 1 && - (!zr->frame_num || zr->JPEG_error)) { - printk(KERN_INFO - "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n", - ZR_DEVNAME(zr), stat, - zr->jpg_settings.odd_even, - zr->jpg_settings. - field_per_buff, - zr->JPEG_missed); - { - char sc[] = "0000"; - char sv[5]; - int i; - strcpy(sv, sc); - for (i = 0; i < 4; i++) { - if (le32_to_cpu(zr->stat_com[i]) & 1) - sv[i] = '1'; - } - sv[4] = 0; - printk(KERN_INFO - "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n", - ZR_DEVNAME(zr), sv, - zr->jpg_que_tail, - zr->jpg_dma_tail, - zr->jpg_dma_head, - zr->jpg_que_head); - } - } else { - if (zr->JPEG_missed > zr->JPEG_max_missed) // Get statistics - zr->JPEG_max_missed = - zr->JPEG_missed; - if (zr->JPEG_missed < - zr->JPEG_min_missed) - zr->JPEG_min_missed = - zr->JPEG_missed; + if ((astat & ZR36057_ISR_JPEGRepIRQ) && + (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || + zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) { + if (zr36067_debug > 1 && (!zr->frame_num || zr->JPEG_error)) { + char sc[] = "0000"; + char sv[5]; + int i; + + printk(KERN_INFO + "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n", + ZR_DEVNAME(zr), stat, + zr->jpg_settings.odd_even, + zr->jpg_settings.field_per_buff, + zr->JPEG_missed); + + strcpy(sv, sc); + for (i = 0; i < 4; i++) { + if (le32_to_cpu(zr->stat_com[i]) & 1) + sv[i] = '1'; } + sv[4] = 0; + printk(KERN_INFO + "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n", + ZR_DEVNAME(zr), sv, + zr->jpg_que_tail, + zr->jpg_dma_tail, + zr->jpg_dma_head, + zr->jpg_que_head); + } else { + /* Get statistics */ + if (zr->JPEG_missed > zr->JPEG_max_missed) + zr->JPEG_max_missed = zr->JPEG_missed; + if (zr->JPEG_missed < zr->JPEG_min_missed) + zr->JPEG_min_missed = zr->JPEG_missed; + } - if (zr36067_debug > 2 && zr->frame_num < 6) { - int i; - printk("%s: seq=%ld stat_com:", - ZR_DEVNAME(zr), zr->jpg_seq_num); - for (i = 0; i < 4; i++) { - printk(" %08x", - le32_to_cpu(zr->stat_com[i])); - } - printk("\n"); + if (zr36067_debug > 2 && zr->frame_num < 6) { + int i; + + printk(KERN_INFO "%s: seq=%ld stat_com:", + ZR_DEVNAME(zr), zr->jpg_seq_num); + for (i = 0; i < 4; i++) { + printk(KERN_CONT " %08x", + le32_to_cpu(zr->stat_com[i])); } - zr->frame_num++; - zr->JPEG_missed = 0; - zr->JPEG_error = 0; - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - wake_up_interruptible(&zr->jpg_capq); - } /*else { - dprintk(1, - KERN_ERR - "%s: JPEG interrupt while not in motion (de)compress mode!\n", - ZR_DEVNAME(zr)); - }*/ + printk(KERN_CONT "\n"); + } + zr->frame_num++; + zr->JPEG_missed = 0; + zr->JPEG_error = 0; + zoran_reap_stat_com(zr); + zoran_feed_stat_com(zr); + wake_up_interruptible(&zr->jpg_capq); } #endif /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */ @@ -1591,8 +1546,7 @@ zoran_irq (int irq, zr->JPEG_missed > 25 || zr->JPEG_error == 1 || ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) && - (zr->frame_num & (zr->JPEG_missed > - zr->jpg_settings.field_per_buff)))) { + (zr->frame_num & (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) { error_handler(zr, astat, stat); } diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 6a2607998..18c3516f8 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2315,7 +2315,7 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, } /* we actually need to set 'real' parameters now */ - if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT) + if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT) settings.TmpDcm = 1; else settings.TmpDcm = 2; @@ -2502,7 +2502,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { dprintk(1, KERN_ERR - "%s: VIDIOC_REQBUFS - buffers allready allocated\n", + "%s: VIDIOC_REQBUFS - buffers already allocated\n", ZR_DEVNAME(zr)); res = -EBUSY; goto v4l2reqbuf_unlock_and_return; -- cgit v1.2.3 From 796fbda0aa38a68a6ba7451fb0cb1974f36cf956 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 21:11:17 +0100 Subject: zoran: fix TRY_FMT support From: Hans Verkuil Actually try to turn the format into something usable rather than just rejecting it if it isn't perfect. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_card.c | 63 ++++++++++++++++++-------- linux/drivers/media/video/zoran/zoran_card.h | 3 +- linux/drivers/media/video/zoran/zoran_driver.c | 21 +++++++-- 3 files changed, 63 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index ef0533086..552204bab 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -836,7 +836,8 @@ zoran_unregister_i2c (struct zoran *zr) int zoran_check_jpg_settings (struct zoran *zr, - struct zoran_jpg_settings *settings) + struct zoran_jpg_settings *settings, + int try) { int err = 0, err0 = 0; @@ -901,35 +902,61 @@ zoran_check_jpg_settings (struct zoran *zr, /* We have to check the data the user has set */ if (settings->HorDcm != 1 && settings->HorDcm != 2 && - (zr->card.type == DC10_new || settings->HorDcm != 4)) + (zr->card.type == DC10_new || settings->HorDcm != 4)) { + settings->HorDcm = clamp(settings->HorDcm, 1, 2); err0++; - if (settings->VerDcm != 1 && settings->VerDcm != 2) + } + if (settings->VerDcm != 1 && settings->VerDcm != 2) { + settings->VerDcm = clamp(settings->VerDcm, 1, 2); err0++; - if (settings->TmpDcm != 1 && settings->TmpDcm != 2) + } + if (settings->TmpDcm != 1 && settings->TmpDcm != 2) { + settings->TmpDcm = clamp(settings->TmpDcm, 1, 2); err0++; + } if (settings->field_per_buff != 1 && - settings->field_per_buff != 2) + settings->field_per_buff != 2) { + settings->field_per_buff = clamp(settings->field_per_buff, 1, 2); err0++; - if (settings->img_x < 0) + } + if (settings->img_x < 0) { + settings->img_x = 0; err0++; - if (settings->img_y < 0) + } + if (settings->img_y < 0) { + settings->img_y = 0; err0++; - if (settings->img_width < 0) + } + if (settings->img_width < 0 || settings->img_width > BUZ_MAX_WIDTH) { + settings->img_width = clamp(settings->img_width, 0, (int)BUZ_MAX_WIDTH); err0++; - if (settings->img_height < 0) + } + if (settings->img_height < 0 || settings->img_height > BUZ_MAX_HEIGHT / 2) { + settings->img_height = clamp(settings->img_height, 0, BUZ_MAX_HEIGHT / 2); err0++; - if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) + } + if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) { + settings->img_x = BUZ_MAX_WIDTH - settings->img_width; + err0++; + } + if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) { + settings->img_y = BUZ_MAX_HEIGHT / 2 - settings->img_height; err0++; - if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) + } + if (settings->img_width % (16 * settings->HorDcm) != 0) { + settings->img_width -= settings->img_width % (16 * settings->HorDcm); + if (settings->img_width == 0) + settings->img_width = 16 * settings->HorDcm; + err0++; + } + if (settings->img_height % (8 * settings->VerDcm) != 0) { + settings->img_height -= settings->img_height % (8 * settings->VerDcm); + if (settings->img_height == 0) + settings->img_height = 8 * settings->VerDcm; err0++; - if (settings->HorDcm && settings->VerDcm) { - if (settings->img_width % (16 * settings->HorDcm) != 0) - err0++; - if (settings->img_height % (8 * settings->VerDcm) != 0) - err0++; } - if (err0) { + if (!try && err0) { dprintk(1, KERN_ERR "%s: check_jpg_settings() - error in params for decimation = 0\n", @@ -1019,7 +1046,7 @@ zoran_open_init_params (struct zoran *zr) sizeof(zr->jpg_settings.jpg_comp.COM_data)); zr->jpg_settings.jpg_comp.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT; - i = zoran_check_jpg_settings(zr, &zr->jpg_settings); + i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0); if (i) dprintk(1, KERN_ERR diff --git a/linux/drivers/media/video/zoran/zoran_card.h b/linux/drivers/media/video/zoran/zoran_card.h index 4507bdc5e..4936fead7 100644 --- a/linux/drivers/media/video/zoran/zoran_card.h +++ b/linux/drivers/media/video/zoran/zoran_card.h @@ -44,7 +44,8 @@ extern int zr36067_debug; extern struct video_device zoran_template; extern int zoran_check_jpg_settings(struct zoran *zr, - struct zoran_jpg_settings *settings); + struct zoran_jpg_settings *settings, + int try); extern void zoran_open_init_params(struct zoran *zr); extern void zoran_vdev_release(struct video_device *vdev); diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 18c3516f8..748df1fcf 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1798,7 +1798,7 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) /* Check the params first before overwriting our * nternal values */ - if (zoran_check_jpg_settings(zr, &settings)) { + if (zoran_check_jpg_settings(zr, &settings, 0)) { res = -EINVAL; goto sparams_unlock_and_return; } @@ -2206,7 +2206,7 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, settings.field_per_buff = 1; /* check */ - res = zoran_check_jpg_settings(zr, &settings); + res = zoran_check_jpg_settings(zr, &settings, 1); if (res) goto tryfmt_unlock_and_return; @@ -2232,6 +2232,7 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; + int bpp; int i; if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) @@ -2248,6 +2249,8 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, return -EINVAL; } + bpp = (zoran_formats[i].depth + 7) / 8; + fmt->fmt.pix.width &= ~((bpp == 2) ? 1 : 3); if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) fmt->fmt.pix.width = BUZ_MAX_WIDTH; if (fmt->fmt.pix.width < BUZ_MIN_WIDTH) @@ -2335,8 +2338,16 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, else settings.field_per_buff = 1; + if (settings.HorDcm > 1) { + settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0; + settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH; + } else { + settings.img_x = 0; + settings.img_width = BUZ_MAX_WIDTH; + } + /* check */ - res = zoran_check_jpg_settings(zr, &settings); + res = zoran_check_jpg_settings(zr, &settings, 0); if (res) goto sfmtjpg_unlock_and_return; @@ -3217,7 +3228,7 @@ static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop) settings.img_height = crop->c.height; /* check validity */ - res = zoran_check_jpg_settings(zr, &settings); + res = zoran_check_jpg_settings(zr, &settings, 0); if (res) goto scrop_unlock_and_return; @@ -3279,7 +3290,7 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, goto sjpegc_unlock_and_return; } - res = zoran_check_jpg_settings(zr, &settings); + res = zoran_check_jpg_settings(zr, &settings, 0); if (res) goto sjpegc_unlock_and_return; if (!fh->jpg_buffers.allocated) -- cgit v1.2.3 From 3c0d4e5fb734b1afe1cd961a4c61b90c8c6d5d9d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 21:12:34 +0100 Subject: zoran: fix G_FMT From: Hans Verkuil Returned height was really height / 2. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 748df1fcf..98741c992 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2084,7 +2084,7 @@ static int zoran_g_fmt_vid_out(struct file *file, void *__fh, mutex_lock(&zr->resource_lock); fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm; - fmt->fmt.pix.height = fh->jpg_settings.img_height / + fmt->fmt.pix.height = fh->jpg_settings.img_height * 2 / (fh->jpg_settings.VerDcm * fh->jpg_settings.TmpDcm); fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&fh->jpg_settings); fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; -- cgit v1.2.3 From 42175ea795fa141cd724faf722cdbbd59358ad3c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 21:15:46 +0100 Subject: zoran: if reqbufs is called with count == 0, do a streamoff. From: Hans Verkuil count == 0 has a special meaning, implement this. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 98741c992..e67c6caac 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2494,6 +2494,8 @@ static int zoran_overlay(struct file *file, void *__fh, unsigned int on) return res; } +static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type); + static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req) { struct zoran_fh *fh = __fh; @@ -2501,17 +2503,19 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe int res = 0; if (req->memory != V4L2_MEMORY_MMAP) { - dprintk(1, + dprintk(2, KERN_ERR "%s: only MEMORY_MMAP capture is supported, not %d\n", ZR_DEVNAME(zr), req->memory); return -EINVAL; } - mutex_lock(&zr->resource_lock); + if (req->count == 0) + return zoran_streamoff(file, fh, req->type); + mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { - dprintk(1, + dprintk(2, KERN_ERR "%s: VIDIOC_REQBUFS - buffers already allocated\n", ZR_DEVNAME(zr)); -- cgit v1.2.3 From 441ce16cab1f8d7a546eeb785da0f9caf28ef7cc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 21:26:06 +0100 Subject: zoran et al: convert zoran i2c modules to V4L2. From: Hans Verkuil The zoran i2c modules were still using V4L1 internally. Replace this with V4L2. Also deleted saa7111.c and saa7114.c, we use saa7115.c instead. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Kconfig | 28 +- linux/drivers/media/video/Makefile | 2 - linux/drivers/media/video/adv7170.c | 74 +- linux/drivers/media/video/adv7175.c | 81 +- linux/drivers/media/video/bt819.c | 271 +++--- linux/drivers/media/video/bt856.c | 92 +- linux/drivers/media/video/bt866.c | 67 +- linux/drivers/media/video/ks0127.c | 140 ++-- linux/drivers/media/video/saa7110.c | 208 ++--- linux/drivers/media/video/saa7111.c | 497 ----------- linux/drivers/media/video/saa7114.c | 1073 ------------------------ linux/drivers/media/video/saa7185.c | 78 +- linux/drivers/media/video/vpx3220.c | 220 ++--- linux/drivers/media/video/zoran/Kconfig | 4 +- linux/drivers/media/video/zoran/zoran.h | 6 +- linux/drivers/media/video/zoran/zoran_card.c | 60 +- linux/drivers/media/video/zoran/zoran_device.c | 61 +- linux/drivers/media/video/zoran/zoran_driver.c | 220 ++--- 18 files changed, 642 insertions(+), 2540 deletions(-) delete mode 100644 linux/drivers/media/video/saa7111.c delete mode 100644 linux/drivers/media/video/saa7114.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 19cf3b8f6..e671beb59 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -307,38 +307,18 @@ config VIDEO_TCM825X config VIDEO_SAA7110 tristate "Philips SAA7110 video decoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for the Philips SAA7110 video decoders. To compile this driver as a module, choose M here: the module will be called saa7110. -config VIDEO_SAA7111 - tristate "Philips SAA7111 video decoder" - depends on VIDEO_V4L1 && I2C - ---help--- - Support for the Philips SAA711 video decoder. - - To compile this driver as a module, choose M here: the - module will be called saa7111. - -config VIDEO_SAA7114 - tristate "Philips SAA7114 video decoder" - depends on VIDEO_V4L1 && I2C - ---help--- - Support for the Philips SAA7114 video decoder. This driver - is used only on Zoran driver and should be moved soon to - SAA711x module. - - To compile this driver as a module, choose M here: the - module will be called saa7114. - config VIDEO_SAA711X - tristate "Philips SAA7113/4/5 video decoders" + tristate "Philips SAA7111/3/4/5 video decoders" depends on VIDEO_V4L2 && I2C ---help--- - Support for the Philips SAA7113/4/5 video decoders. + Support for the Philips SAA7111/3/4/5 video decoders. To compile this driver as a module, choose M here: the module will be called saa7115. @@ -639,7 +619,7 @@ config VIDEO_MXB depends on PCI && VIDEO_V4L1 && I2C select VIDEO_SAA7146_VV select VIDEO_TUNER - select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 72f6d03d2..263c2264d 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -43,8 +43,6 @@ obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o -obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o -obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 0a319ad8e..323cea3a9 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -53,9 +53,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct adv7170 { unsigned char reg[128]; - int norm; + v4l2_std_id norm; int input; - int enable; int bright; int contrast; int hue; @@ -63,7 +62,6 @@ struct adv7170 { }; static char *inputs[] = { "pass_through", "play_back" }; -static char *norms[] = { "PAL", "NTSC" }; /* ----------------------------------------------------------------------- */ @@ -192,7 +190,7 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) struct adv7170 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: #if 0 /* keep */ /* This is just for testing!!! */ adv7170_write_block(client, init_common, @@ -202,63 +200,47 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) #endif break; - case ENCODER_GET_CAPABILITIES: + case VIDIOC_INT_S_STD_OUTPUT: { - struct video_encoder_capability *cap = arg; + v4l2_std_id iarg = *(v4l2_std_id *) arg; - cap->flags = VIDEO_ENCODER_PAL | - VIDEO_ENCODER_NTSC; - cap->inputs = 2; - cap->outputs = 1; - break; - } - - case ENCODER_SET_NORM: - { - int iarg = *(int *) arg; - - v4l_dbg(1, debug, client, "set norm %d\n", iarg); + v4l_dbg(1, debug, client, "set norm %llx\n", iarg); - switch (iarg) { - case VIDEO_MODE_NTSC: + if (iarg & V4L2_STD_NTSC) { adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); if (encoder->input == 0) adv7170_write(client, 0x02, 0x0e); // Enable genlock adv7170_write(client, 0x07, TR0MODE | TR0RST); adv7170_write(client, 0x07, TR0MODE); - break; - - case VIDEO_MODE_PAL: + } else if (iarg & V4L2_STD_PAL) { adv7170_write_block(client, init_PAL, sizeof(init_PAL)); if (encoder->input == 0) adv7170_write(client, 0x02, 0x0e); // Enable genlock adv7170_write(client, 0x07, TR0MODE | TR0RST); adv7170_write(client, 0x07, TR0MODE); - break; - - default: - v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg); + } else { + v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg); return -EINVAL; } - v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]); + v4l_dbg(1, debug, client, "switched to %llx\n", iarg); encoder->norm = iarg; break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int iarg = *(int *) arg; + struct v4l2_routing *route = arg; /* RJ: *iarg = 0: input is from decoder *iarg = 1: input is from ZR36060 *iarg = 2: color bar */ v4l_dbg(1, debug, client, "set input from %s\n", - iarg == 0 ? "decoder" : "ZR36060"); + route->input == 0 ? "decoder" : "ZR36060"); - switch (iarg) { + switch (route->input) { case 0: adv7170_write(client, 0x01, 0x20); adv7170_write(client, 0x08, TR1CAPT); /* TR1 */ @@ -278,30 +260,11 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) break; default: - v4l_dbg(1, debug, client, "illegal input: %d\n", iarg); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]); - encoder->input = iarg; - break; - } - - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) { + v4l_dbg(1, debug, client, "illegal input: %d\n", route->input); return -EINVAL; } - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; + v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]); + encoder->input = route->input; break; } @@ -338,9 +301,8 @@ static int adv7170_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - encoder->norm = VIDEO_MODE_NTSC; + encoder->norm = V4L2_STD_NTSC; encoder->input = 0; - encoder->enable = 1; i2c_set_clientdata(client, encoder); i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c index 281a3f53c..11c92440e 100644 --- a/linux/drivers/media/video/adv7175.c +++ b/linux/drivers/media/video/adv7175.c @@ -47,9 +47,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct adv7175 { - int norm; + v4l2_std_id norm; int input; - int enable; int bright; int contrast; int hue; @@ -60,7 +59,6 @@ struct adv7175 { #define I2C_ADV7176 0x54 static char *inputs[] = { "pass_through", "play_back", "color_bar" }; -static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" }; /* ----------------------------------------------------------------------- */ @@ -190,7 +188,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) struct adv7175 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: /* This is just for testing!!! */ adv7175_write_block(client, init_common, sizeof(init_common)); @@ -198,42 +196,25 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) adv7175_write(client, 0x07, TR0MODE); break; - case ENCODER_GET_CAPABILITIES: + case VIDIOC_INT_S_STD_OUTPUT: { - struct video_encoder_capability *cap = arg; + v4l2_std_id iarg = *(v4l2_std_id *) arg; - cap->flags = VIDEO_ENCODER_PAL | - VIDEO_ENCODER_NTSC | - VIDEO_ENCODER_SECAM; /* well, hacky */ - cap->inputs = 2; - cap->outputs = 1; - break; - } - - case ENCODER_SET_NORM: - { - int iarg = *(int *) arg; - - switch (iarg) { - case VIDEO_MODE_NTSC: + if (iarg & V4L2_STD_NTSC) { adv7175_write_block(client, init_ntsc, sizeof(init_ntsc)); if (encoder->input == 0) adv7175_write(client, 0x0d, 0x4f); // Enable genlock adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - break; - - case VIDEO_MODE_PAL: + } else if (iarg & V4L2_STD_PAL) { adv7175_write_block(client, init_pal, sizeof(init_pal)); if (encoder->input == 0) adv7175_write(client, 0x0d, 0x4f); // Enable genlock adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - break; - - case VIDEO_MODE_SECAM: // WARNING! ADV7176 does not support SECAM. + } else if (iarg & V4L2_STD_SECAM) { /* This is an attempt to convert * SECAM->PAL (typically it does not work * due to genlock: when decoder is in SECAM @@ -246,33 +227,32 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) adv7175_write(client, 0x0d, 0x49); // Disable genlock adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - break; - default: - v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg); + } else { + v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg); return -EINVAL; } - v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]); + v4l_dbg(1, debug, client, "switched to %llx\n", iarg); encoder->norm = iarg; break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int iarg = *(int *) arg; + struct v4l2_routing *route = arg; /* RJ: *iarg = 0: input is from SAA7110 *iarg = 1: input is from ZR36060 *iarg = 2: color bar */ - switch (iarg) { + switch (route->input) { case 0: adv7175_write(client, 0x01, 0x00); - if (encoder->norm == VIDEO_MODE_NTSC) + if (encoder->norm & V4L2_STD_NTSC) set_subcarrier_freq(client, 1); adv7175_write(client, 0x0c, TR1CAPT); /* TR1 */ - if (encoder->norm == VIDEO_MODE_SECAM) + if (encoder->norm & V4L2_STD_SECAM) adv7175_write(client, 0x0d, 0x49); // Disable genlock else adv7175_write(client, 0x0d, 0x4f); // Enable genlock @@ -284,7 +264,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) case 1: adv7175_write(client, 0x01, 0x00); - if (encoder->norm == VIDEO_MODE_NTSC) + if (encoder->norm & V4L2_STD_NTSC) set_subcarrier_freq(client, 0); adv7175_write(client, 0x0c, TR1PLAY); /* TR1 */ @@ -297,7 +277,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) case 2: adv7175_write(client, 0x01, 0x80); - if (encoder->norm == VIDEO_MODE_NTSC) + if (encoder->norm & V4L2_STD_NTSC) set_subcarrier_freq(client, 0); adv7175_write(client, 0x0d, 0x49); @@ -307,29 +287,11 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) break; default: - v4l_dbg(1, debug, client, "illegal input: %d\n", iarg); + v4l_dbg(1, debug, client, "illegal input: %d\n", route->input); return -EINVAL; } - v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]); - encoder->input = iarg; - break; - } - - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; + v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]); + encoder->input = route->input; break; } @@ -370,9 +332,8 @@ static int adv7175_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - encoder->norm = VIDEO_MODE_PAL; + encoder->norm = V4L2_STD_NTSC; encoder->input = 0; - encoder->enable = 1; i2c_set_clientdata(client, encoder); i = adv7175_write_block(client, init_common, sizeof(init_common)); diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index 201dd9277..cd85ea462 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -55,7 +55,7 @@ struct bt819 { unsigned char reg[32]; int initialized; - int norm; + v4l2_std_id norm; int input; int enable; int bright; @@ -179,7 +179,7 @@ static int bt819_init(struct i2c_client *client) 0x1a, 0x80, /* 0x1a ADC Interface */ }; - struct timing *timing = &timing_data[decoder->norm]; + struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0]; init[0x03 * 2 - 1] = (((timing->vdelay >> 8) & 0x03) << 6) | @@ -193,7 +193,7 @@ static int bt819_init(struct i2c_client *client) init[0x08 * 2 - 1] = timing->hscale >> 8; init[0x09 * 2 - 1] = timing->hscale & 0xff; /* 0x15 in array is address 0x19 */ - init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93; /* Chroma burst delay */ + init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93; /* Chroma burst delay */ /* reset */ bt819_write(client, 0x1f, 0x00); mdelay(1); @@ -216,121 +216,93 @@ static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) } switch (cmd) { - case 0: + case VIDIOC_INT_INIT: /* This is just for testing!!! */ bt819_init(client); break; - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_AUTO | - VIDEO_DECODER_CCIR; - cap->inputs = 8; - cap->outputs = 1; - break; - } - - case DECODER_GET_STATUS: - { + case VIDIOC_QUERYSTD: + case VIDIOC_INT_G_INPUT_STATUS: { int *iarg = arg; + v4l2_std_id *istd = arg; int status; - int res; + int res = V4L2_IN_ST_NO_SIGNAL; + v4l2_std_id std; status = bt819_read(client, 0x00); - res = 0; if ((status & 0x80)) - res |= DECODER_STATUS_GOOD; + res = 0; - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - default: - case VIDEO_MODE_AUTO: - if ((status & 0x10)) - res |= DECODER_STATUS_PAL; - else - res |= DECODER_STATUS_NTSC; - break; - } - res |= DECODER_STATUS_COLOR; - *iarg = res; + if ((status & 0x10)) + std = V4L2_STD_PAL; + else + std = V4L2_STD_NTSC; + if (cmd == VIDIOC_QUERYSTD) + *istd = std; + else + *iarg = res; v4l_dbg(1, debug, client, "get status %x\n", *iarg); break; } - case DECODER_SET_NORM: + case VIDIOC_S_STD: { - int *iarg = arg; + v4l2_std_id *iarg = arg; struct timing *timing = NULL; - v4l_dbg(1, debug, client, "set norm %x\n", *iarg); + v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - switch (*iarg) { - case VIDEO_MODE_NTSC: + if (*iarg & V4L2_STD_NTSC) { bt819_setbit(client, 0x01, 0, 1); bt819_setbit(client, 0x01, 1, 0); bt819_setbit(client, 0x01, 5, 0); bt819_write(client, 0x18, 0x68); bt819_write(client, 0x19, 0x5d); /* bt819_setbit(client, 0x1a, 5, 1); */ - timing = &timing_data[VIDEO_MODE_NTSC]; - break; - case VIDEO_MODE_PAL: + timing = &timing_data[1]; + } else if (*iarg & V4L2_STD_PAL) { bt819_setbit(client, 0x01, 0, 1); bt819_setbit(client, 0x01, 1, 1); bt819_setbit(client, 0x01, 5, 1); bt819_write(client, 0x18, 0x7f); bt819_write(client, 0x19, 0x72); /* bt819_setbit(client, 0x1a, 5, 0); */ - timing = &timing_data[VIDEO_MODE_PAL]; - break; - case VIDEO_MODE_AUTO: - bt819_setbit(client, 0x01, 0, 0); - bt819_setbit(client, 0x01, 1, 0); - break; - default: - v4l_dbg(1, debug, client, "unsupported norm %x\n", *iarg); + timing = &timing_data[0]; + } else { + v4l_dbg(1, debug, client, "unsupported norm %llx\n", *iarg); return -EINVAL; } - - if (timing) { - bt819_write(client, 0x03, - (((timing->vdelay >> 8) & 0x03) << 6) | - (((timing->vactive >> 8) & 0x03) << 4) | - (((timing->hdelay >> 8) & 0x03) << 2) | - ((timing->hactive >> 8) & 0x03) ); - bt819_write(client, 0x04, timing->vdelay & 0xff); - bt819_write(client, 0x05, timing->vactive & 0xff); - bt819_write(client, 0x06, timing->hdelay & 0xff); - bt819_write(client, 0x07, timing->hactive & 0xff); - bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff); - bt819_write(client, 0x09, timing->hscale & 0xff); - } - +/* case VIDEO_MODE_AUTO: + bt819_setbit(client, 0x01, 0, 0); + bt819_setbit(client, 0x01, 1, 0);*/ + + bt819_write(client, 0x03, + (((timing->vdelay >> 8) & 0x03) << 6) | + (((timing->vactive >> 8) & 0x03) << 4) | + (((timing->hdelay >> 8) & 0x03) << 2) | + ((timing->hactive >> 8) & 0x03)); + bt819_write(client, 0x04, timing->vdelay & 0xff); + bt819_write(client, 0x05, timing->vactive & 0xff); + bt819_write(client, 0x06, timing->hdelay & 0xff); + bt819_write(client, 0x07, timing->hactive & 0xff); + bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff); + bt819_write(client, 0x09, timing->hscale & 0xff); decoder->norm = *iarg; break; } - case DECODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg; + struct v4l2_routing *route = arg; - v4l_dbg(1, debug, client, "set input %x\n", *iarg); + v4l_dbg(1, debug, client, "set input %x\n", route->input); - if (*iarg < 0 || *iarg > 7) + if (route->input < 0 || route->input > 7) return -EINVAL; - if (decoder->input != *iarg) { - decoder->input = *iarg; + if (decoder->input != route->input) { + decoder->input = route->input; /* select mode */ if (decoder->input == 0) { bt819_setbit(client, 0x0b, 6, 0); @@ -343,75 +315,116 @@ static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case DECODER_SET_OUTPUT: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: { - int *iarg = arg; + int enable = cmd == VIDIOC_STREAMON; - v4l_dbg(1, debug, client, "set output %x\n", *iarg); + v4l_dbg(1, debug, client, "enable output %x\n", enable); - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; + if (decoder->enable != enable) { + decoder->enable = enable; + bt819_setbit(client, 0x16, 7, !enable); + } break; } - case DECODER_ENABLE_OUTPUT: + case VIDIOC_QUERYCTRL: { - int *iarg = arg; - int enable = (*iarg != 0); + struct v4l2_queryctrl *qc = arg; - v4l_dbg(1, debug, client, "enable output %x\n", *iarg); + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; - if (decoder->enable != enable) { - decoder->enable = enable; - bt819_setbit(client, 0x16, 7, !enable); + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); + break; + + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); + break; + + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; + + default: + return -EINVAL; } break; } - case DECODER_SET_PICTURE: + case VIDIOC_S_CTRL: { - struct video_picture *pic = arg; + struct v4l2_control *ctrl = arg; - v4l_dbg(1, debug, client, - "set picture brightness %d contrast %d colour %d\n", - pic->brightness, pic->contrast, pic->colour); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + bt819_write(client, 0x0a, decoder->bright); + } + break; + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + decoder->contrast = ctrl->value; + bt819_write(client, 0x0c, + decoder->contrast & 0xff); + bt819_setbit(client, 0x0b, 2, + ((decoder->contrast >> 8) & 0x01)); + } + break; - if (decoder->bright != pic->brightness) { - /* We want -128 to 127 we get 0-65535 */ - decoder->bright = pic->brightness; - bt819_write(client, 0x0a, - (decoder->bright >> 8) - 128); - } + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + bt819_write(client, 0x0d, + (decoder->sat >> 7) & 0xff); + bt819_setbit(client, 0x0b, 1, + ((decoder->sat >> 15) & 0x01)); + + /* Ratio between U gain and V gain must stay the same as + the ratio between the default U and V gain values. */ + temp = (decoder->sat * 180) / 254; + bt819_write(client, 0x0e, (temp >> 7) & 0xff); + bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01); + } + break; - if (decoder->contrast != pic->contrast) { - /* We want 0 to 511 we get 0-65535 */ - decoder->contrast = pic->contrast; - bt819_write(client, 0x0c, - (decoder->contrast >> 7) & 0xff); - bt819_setbit(client, 0x0b, 2, - ((decoder->contrast >> 15) & 0x01)); + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + bt819_write(client, 0x0f, decoder->hue); + } + break; + default: + return -EINVAL; } + break; + } - if (decoder->sat != pic->colour) { - /* We want 0 to 511 we get 0-65535 */ - decoder->sat = pic->colour; - bt819_write(client, 0x0d, - (decoder->sat >> 7) & 0xff); - bt819_setbit(client, 0x0b, 1, - ((decoder->sat >> 15) & 0x01)); - - temp = (decoder->sat * 201) / 237; - bt819_write(client, 0x0e, (temp >> 7) & 0xff); - bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01); - } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - bt819_write(client, 0x0f, - 128 - (decoder->hue >> 8)); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; + break; + default: + return -EINVAL; } break; } @@ -463,13 +476,13 @@ static int bt819_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; - decoder->norm = VIDEO_MODE_NTSC; + decoder->norm = V4L2_STD_NTSC; decoder->input = 0; decoder->enable = 1; - decoder->bright = 32768; - decoder->contrast = 32768; - decoder->hue = 32768; - decoder->sat = 32768; + decoder->bright = 0; + decoder->contrast = 0xd8; /* 100% of original signal */ + decoder->hue = 0; + decoder->sat = 0xfe; /* 100% of original signal */ decoder->initialized = 0; i2c_set_clientdata(client, decoder); diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c index 89c4061c7..626019e49 100644 --- a/linux/drivers/media/video/bt856.c +++ b/linux/drivers/media/video/bt856.c @@ -56,8 +56,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct bt856 { unsigned char reg[BT856_NR_REG]; - int norm; - int enable; + v4l2_std_id norm; }; /* ----------------------------------------------------------------------- */ @@ -97,7 +96,7 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) struct bt856 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: /* This is just for testing!!! */ v4l_dbg(1, debug, client, "init\n"); bt856_write(client, 0xdc, 0x18); @@ -108,15 +107,10 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) //bt856_setbit(client, 0xdc, 6, 0); bt856_setbit(client, 0xdc, 4, 1); - switch (encoder->norm) { - case VIDEO_MODE_NTSC: + if (encoder->norm & V4L2_STD_NTSC) bt856_setbit(client, 0xdc, 2, 0); - break; - - case VIDEO_MODE_PAL: + else bt856_setbit(client, 0xdc, 2, 1); - break; - } bt856_setbit(client, 0xdc, 1, 1); bt856_setbit(client, 0xde, 4, 0); @@ -125,38 +119,19 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) bt856_dump(client); break; - case ENCODER_GET_CAPABILITIES: + case VIDIOC_INT_S_STD_OUTPUT: { - struct video_encoder_capability *cap = arg; - - v4l_dbg(1, debug, client, "get capabilities\n"); + v4l2_std_id *iarg = arg; - cap->flags = VIDEO_ENCODER_PAL | - VIDEO_ENCODER_NTSC | - VIDEO_ENCODER_CCIR; - cap->inputs = 2; - cap->outputs = 1; - break; - } - - case ENCODER_SET_NORM: - { - int *iarg = arg; + v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - v4l_dbg(1, debug, client, "set norm %d\n", *iarg); - - switch (*iarg) { - case VIDEO_MODE_NTSC: + if (*iarg & V4L2_STD_NTSC) { bt856_setbit(client, 0xdc, 2, 0); - break; - - case VIDEO_MODE_PAL: + } else if (*iarg & V4L2_STD_PAL) { bt856_setbit(client, 0xdc, 2, 1); bt856_setbit(client, 0xda, 0, 0); //bt856_setbit(client, 0xda, 0, 1); - break; - - default: + } else { return -EINVAL; } encoder->norm = *iarg; @@ -165,16 +140,16 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg; + struct v4l2_routing *route = arg; - v4l_dbg(1, debug, client, "set input %d\n", *iarg); + v4l_dbg(1, debug, client, "set input %d\n", route->input); /* We only have video bus. - * iarg = 0: input is from bt819 - * iarg = 1: input is from ZR36060 */ - switch (*iarg) { + * route->input= 0: input is from bt819 + * route->input= 1: input is from ZR36060 */ + switch (route->input) { case 0: bt856_setbit(client, 0xde, 4, 0); bt856_setbit(client, 0xde, 3, 1); @@ -200,28 +175,6 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set output %d\n", *iarg); - - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; - - v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); - break; - } - default: return -EINVAL; } @@ -250,8 +203,7 @@ static int bt856_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - encoder->norm = VIDEO_MODE_NTSC; - encoder->enable = 1; + encoder->norm = V4L2_STD_NTSC; i2c_set_clientdata(client, encoder); bt856_write(client, 0xdc, 0x18); @@ -262,16 +214,10 @@ static int bt856_probe(struct i2c_client *client, //bt856_setbit(client, 0xdc, 6, 0); bt856_setbit(client, 0xdc, 4, 1); - switch (encoder->norm) { - - case VIDEO_MODE_NTSC: + if (encoder->norm & V4L2_STD_NTSC) bt856_setbit(client, 0xdc, 2, 0); - break; - - case VIDEO_MODE_PAL: + else bt856_setbit(client, 0xdc, 2, 1); - break; - } bt856_setbit(client, 0xdc, 1, 1); bt856_setbit(client, 0xde, 4, 0); diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index aaa985c8e..5aed3c7f1 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -53,8 +53,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct bt866 { u8 reg[256]; - int norm; - int enable; + v4l2_std_id norm; int bright; int contrast; int hue; @@ -95,44 +94,21 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) struct bt866 *encoder = i2c_get_clientdata(client); switch (cmd) { - case ENCODER_GET_CAPABILITIES: + case VIDIOC_INT_S_STD_OUTPUT: { - struct video_encoder_capability *cap = arg; + v4l2_std_id *iarg = arg; - v4l_dbg(1, debug, client, "get capabilities\n"); + v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - cap->flags - = VIDEO_ENCODER_PAL - | VIDEO_ENCODER_NTSC - | VIDEO_ENCODER_CCIR; - cap->inputs = 2; - cap->outputs = 1; - break; - } - - case ENCODER_SET_NORM: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set norm %d\n", *iarg); - - switch (*iarg) { - case VIDEO_MODE_NTSC: - break; - - case VIDEO_MODE_PAL: - break; - - default: + if (!(*iarg & (V4L2_STD_NTSC | V4L2_STD_PAL))) return -EINVAL; - } encoder->norm = *iarg; break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg; + struct v4l2_routing *route = arg; static const __u8 init[] = { 0xc8, 0xcc, /* CRSCALE */ 0xca, 0x91, /* CBSCALE */ @@ -168,7 +144,7 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) val = encoder->reg[0xdc]; - if (*iarg == 0) + if (route->input == 0) val |= 0x40; /* CBSWAP */ else val &= ~0x40; /* !CBSWAP */ @@ -176,15 +152,15 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) bt866_write(client, 0xdc, val); val = encoder->reg[0xcc]; - if (*iarg == 2) + if (route->input == 2) val |= 0x01; /* OSDBAR */ else val &= ~0x01; /* !OSDBAR */ bt866_write(client, 0xcc, val); - v4l_dbg(1, debug, client, "set input %d\n", *iarg); + v4l_dbg(1, debug, client, "set input %d\n", route->input); - switch (*iarg) { + switch (route->input) { case 0: break; case 1: @@ -195,27 +171,6 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set output %d\n", *iarg); - - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - encoder->enable = !!*iarg; - - v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); - break; - } - case 4711: { int *iarg = arg; diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index 16526165b..3b565c039 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -202,7 +202,7 @@ struct ks0127 { int format_height; int cap_width; int cap_height; - int norm; + v4l2_std_id norm; int ks_type; u8 regs[256]; }; @@ -409,20 +409,22 @@ static void ks0127_reset(struct i2c_client *c) static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) { struct ks0127 *ks = i2c_get_clientdata(c); + struct v4l2_routing *route = arg; int *iarg = (int *)arg; + v4l2_std_id *istd = arg; int status; if (!ks) return -ENODEV; switch (cmd) { - case DECODER_INIT: - v4l_dbg(1, debug, c, "DECODER_INIT\n"); + case VIDIOC_INT_INIT: + v4l_dbg(1, debug, c, "VIDIOC_INT_INIT\n"); ks0127_reset(c); break; - case DECODER_SET_INPUT: - switch(*iarg) { + case VIDIOC_INT_S_VIDEO_ROUTING: + switch (route->input) { case KS_INPUT_COMPOSITE_1: case KS_INPUT_COMPOSITE_2: case KS_INPUT_COMPOSITE_3: @@ -430,7 +432,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) case KS_INPUT_COMPOSITE_5: case KS_INPUT_COMPOSITE_6: v4l_dbg(1, debug, c, - "DECODER_SET_INPUT %d: Composite\n", *iarg); + "VIDIOC_S_INPUT %d: Composite\n", *iarg); /* autodetect 50/60 Hz */ ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ @@ -464,7 +466,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) case KS_INPUT_SVIDEO_2: case KS_INPUT_SVIDEO_3: v4l_dbg(1, debug, c, - "DECODER_SET_INPUT %d: S-Video\n", *iarg); + "VIDIOC_S_INPUT %d: S-Video\n", *iarg); /* autodetect 50/60 Hz */ ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ @@ -496,9 +498,8 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) case KS_INPUT_YUV656: v4l_dbg(1, debug, c, - "DECODER_SET_INPUT 15: YUV656\n"); - if (ks->norm == VIDEO_MODE_NTSC || - ks->norm == KS_STD_PAL_M) + "VIDIOC_S_INPUT 15: YUV656\n"); + if (ks->norm & V4L2_STD_525_60) /* force 60 Hz */ ks0127_and_or(c, KS_CMDA, 0xfc, 0x03); else @@ -542,7 +543,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) default: v4l_dbg(1, debug, c, - "DECODER_SET_INPUT: Unknown input %d\n", *iarg); + "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input); break; } @@ -551,33 +552,18 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]); break; - case DECODER_SET_OUTPUT: - switch(*iarg) { - case KS_OUTPUT_YUV656E: - v4l_dbg(1, debug, c, - "DECODER_SET_OUTPUT: OUTPUT_YUV656E (Missing)\n"); - return -EINVAL; - - case KS_OUTPUT_EXV: - v4l_dbg(1, debug, c, - "DECODER_SET_OUTPUT: OUTPUT_EXV\n"); - ks0127_and_or(c, KS_OFMTA, 0xf0, 0x09); - break; - } - break; - - case DECODER_SET_NORM: /* sam This block mixes old and new norm names... */ + case VIDIOC_S_STD: /* sam This block mixes old and new norm names... */ /* Set to automatic SECAM/Fsc mode */ ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); - ks->norm = *iarg; - switch (*iarg) { + ks->norm = *istd; +#if 0 /* this is untested !! */ /* It just detects PAL_N/NTSC_M (no special frequencies) */ /* And you have to set the standard a second time afterwards */ case VIDEO_MODE_AUTO: v4l_dbg(1, debug, c, - "DECODER_SET_NORM: AUTO\n"); + "VIDIOC_S_STD: AUTO\n"); /* The chip determines the format */ /* based on the current field rate */ @@ -588,40 +574,33 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) ks->format_height = 240; ks->format_width = 704; break; +#endif - case VIDEO_MODE_NTSC: + if (*istd & V4L2_STD_NTSC) { v4l_dbg(1, debug, c, - "DECODER_SET_NORM: NTSC_M\n"); + "VIDIOC_S_STD: NTSC_M\n"); ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); ks->format_height = 240; ks->format_width = 704; - break; - - case KS_STD_NTSC_N: + } else if (*istd & V4L2_STD_PAL_N) { v4l_dbg(1, debug, c, "KS0127_SET_NORM: NTSC_N (fixme)\n"); ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); ks->format_height = 240; ks->format_width = 704; - break; - - case VIDEO_MODE_PAL: + } else if (*istd & V4L2_STD_PAL) { v4l_dbg(1, debug, c, - "DECODER_SET_NORM: PAL_N\n"); + "VIDIOC_S_STD: PAL_N\n"); ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); ks->format_height = 290; ks->format_width = 704; - break; - - case KS_STD_PAL_M: + } else if (*istd & V4L2_STD_PAL_M) { v4l_dbg(1, debug, c, "KS0127_SET_NORM: PAL_M (fixme)\n"); ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); ks->format_height = 290; ks->format_width = 704; - break; - - case VIDEO_MODE_SECAM: + } else if (*istd & V4L2_STD_SECAM) { v4l_dbg(1, debug, c, "KS0127_SET_NORM: SECAM\n"); ks->format_height = 290; @@ -633,29 +612,34 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) schedule_timeout_interruptible(HZ/10+1); /* did it autodetect? */ - if (ks0127_read(c, KS_DEMOD) & 0x40) - break; - - /* force to secam mode */ - ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f); - break; - - default: + if (!(ks0127_read(c, KS_DEMOD) & 0x40)) + /* force to secam mode */ + ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f); + } else { v4l_dbg(1, debug, c, - "DECODER_SET_NORM: Unknown norm %d\n", *iarg); - break; + "VIDIOC_S_STD: Unknown norm %llx\n", *istd); } break; - case DECODER_SET_PICTURE: + case VIDIOC_QUERYCTRL: + { + return -EINVAL; + } + + case VIDIOC_S_CTRL: v4l_dbg(1, debug, c, - "DECODER_SET_PICTURE: not yet supported\n"); + "VIDIOC_S_CTRL: not yet supported\n"); return -EINVAL; - /* sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE */ - /* sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE */ - /* sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? */ - /* sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE */ + case VIDIOC_G_CTRL: + v4l_dbg(1, debug, c, + "VIDIOC_G_CTRL: not yet supported\n"); + return -EINVAL; + + /* sam todo: KS0127_SET_BRIGHTNESS: Merge into VIDIOC_S_CTRL */ + /* sam todo: KS0127_SET_CONTRAST: Merge into VIDIOC_S_CTRL */ + /* sam todo: KS0127_SET_HUE: Merge into VIDIOC_S_CTRL? */ + /* sam todo: KS0127_SET_SATURATION: Merge into VIDIOC_S_CTRL */ /* sam todo: KS0127_SET_AGC_MODE: */ /* sam todo: KS0127_SET_AGC: */ /* sam todo: KS0127_SET_CHROMA_MODE: */ @@ -671,22 +655,21 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) /* sam todo: KS0127_SET_UNUSEV: */ /* sam todo: KS0127_SET_VSALIGN_MODE: */ - case DECODER_ENABLE_OUTPUT: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: { - int enable; + int enable = cmd == VIDIOC_STREAMON; - iarg = arg; - enable = (*iarg != 0); if (enable) { v4l_dbg(1, debug, c, - "DECODER_ENABLE_OUTPUT on\n"); + "VIDIOC_STREAMON\n"); /* All output pins on */ ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30); /* Obey the OEN pin */ ks0127_and_or(c, KS_CDEM, 0x7f, 0x00); } else { v4l_dbg(1, debug, c, - "DECODER_ENABLE_OUTPUT off\n"); + "VIDIOC_STREAMOFF\n"); /* Video output pins off */ ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00); /* Ignore the OEN pin */ @@ -700,19 +683,26 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) /* sam todo: KS0127_SET_HEIGHT: */ /* sam todo: KS0127_SET_HSCALE: */ - case DECODER_GET_STATUS: - v4l_dbg(1, debug, c, "DECODER_GET_STATUS\n"); - *iarg = 0; + case VIDIOC_QUERYSTD: + case VIDIOC_INT_G_INPUT_STATUS: { + int stat = V4L2_IN_ST_NO_SIGNAL; + v4l2_std_id std = V4L2_STD_ALL; + v4l_dbg(1, debug, c, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); status = ks0127_read(c, KS_STAT); if (!(status & 0x20)) /* NOVID not set */ - *iarg = (*iarg | DECODER_STATUS_GOOD); - if ((status & 0x01)) /* CLOCK set */ - *iarg = (*iarg | DECODER_STATUS_COLOR); + stat = 0; + if (!(status & 0x01)) /* CLOCK set */ + stat |= V4L2_IN_ST_NO_COLOR; if ((status & 0x08)) /* PALDET set */ - *iarg = (*iarg | DECODER_STATUS_PAL); + std = V4L2_STD_PAL; + else + std = V4L2_STD_NTSC; + if (cmd == VIDIOC_QUERYSTD) + *istd = std; else - *iarg = (*iarg | DECODER_STATUS_NTSC); + *iarg = stat; break; + } /* Catch any unknown command */ default: diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index b7afe3124..147c36a71 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -55,7 +55,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct saa7110 { u8 reg[SAA7110_NR_REG]; - int norm; + v4l2_std_id norm; int input; int enable; int bright; @@ -177,7 +177,7 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = { /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02 }; -static int determine_norm(struct i2c_client *client) +static v4l2_std_id determine_norm(struct i2c_client *client) { DEFINE_WAIT(wait); struct saa7110 *decoder = i2c_get_clientdata(client); @@ -199,11 +199,11 @@ static int determine_norm(struct i2c_client *client) if (status & 0x20) { v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status); //saa7110_write(client,0x2E,0x81); - return VIDEO_MODE_NTSC; + return V4L2_STD_NTSC; } v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status); //saa7110_write(client,0x2E,0x9A); - return VIDEO_MODE_PAL; + return V4L2_STD_PAL; } //saa7110_write(client,0x06,0x03); if (status & 0x20) { /* 60Hz */ @@ -212,7 +212,7 @@ static int determine_norm(struct i2c_client *client) saa7110_write(client, 0x0F, 0x50); saa7110_write(client, 0x11, 0x2C); //saa7110_write(client,0x2E,0x81); - return VIDEO_MODE_NTSC; + return V4L2_STD_NTSC; } /* 50Hz -> PAL/SECAM */ @@ -229,10 +229,10 @@ static int determine_norm(struct i2c_client *client) if ((status & 0x03) == 0x01) { v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status); saa7110_write(client, 0x0D, 0x87); - return VIDEO_MODE_SECAM; + return V4L2_STD_SECAM; } v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status); - return VIDEO_MODE_PAL; + return V4L2_STD_PAL; } static int @@ -241,112 +241,81 @@ saa7110_command (struct i2c_client *client, void *arg) { struct saa7110 *decoder = i2c_get_clientdata(client); + struct v4l2_routing *route = arg; + v4l2_std_id std; int v; switch (cmd) { - case 0: + case VIDIOC_INT_INIT: //saa7110_write_block(client, initseq, sizeof(initseq)); break; - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *dc = arg; - - dc->flags = - VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; - dc->inputs = SAA7110_MAX_INPUT; - dc->outputs = SAA7110_MAX_OUTPUT; - break; - } - - case DECODER_GET_STATUS: + case VIDIOC_INT_G_INPUT_STATUS: { + int res = V4L2_IN_ST_NO_SIGNAL; int status; - int res = 0; status = saa7110_read(client); - v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n", + v4l_dbg(1, debug, client, "status=0x%02x norm=%llx\n", status, decoder->norm); if (!(status & 0x40)) - res |= DECODER_STATUS_GOOD; - if (status & 0x03) - res |= DECODER_STATUS_COLOR; + res = 0; + if (!(status & 0x03)) + res |= V4L2_IN_ST_NO_COLOR; - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - case VIDEO_MODE_SECAM: - res |= DECODER_STATUS_SECAM; - break; - } *(int *) arg = res; break; } - case DECODER_SET_NORM: - v = *(int *) arg; - if (decoder->norm != v) { - decoder->norm = v; + case VIDIOC_QUERYSTD: + { + *(v4l2_std_id *)arg = determine_norm(client); + break; + } + + case VIDIOC_S_STD: + std = *(v4l2_std_id *) arg; + if (decoder->norm != std) { + decoder->norm = std; //saa7110_write(client, 0x06, 0x03); - switch (v) { - case VIDEO_MODE_NTSC: + if (std & V4L2_STD_NTSC) { saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x50); saa7110_write(client, 0x11, 0x2C); //saa7110_write(client, 0x2E, 0x81); v4l_dbg(1, debug, client, "switched to NTSC\n"); - break; - case VIDEO_MODE_PAL: + } else if (std & V4L2_STD_PAL) { saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client, 0x2E, 0x9A); v4l_dbg(1, debug, client, "switched to PAL\n"); - break; - case VIDEO_MODE_SECAM: + } else if (std & V4L2_STD_SECAM) { saa7110_write(client, 0x0D, 0x87); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client, 0x2E, 0x9A); v4l_dbg(1, debug, client, "switched to SECAM\n"); - break; - case VIDEO_MODE_AUTO: - v4l_dbg(1, debug, client, "switched to AUTO\n"); - decoder->norm = determine_norm(client); - *(int *) arg = decoder->norm; - break; - default: - return -EPERM; + } else { + return -EINVAL; } } break; - case DECODER_SET_INPUT: - v = *(int *) arg; - if (v < 0 || v >= SAA7110_MAX_INPUT) { - v4l_dbg(1, debug, client, "input=%d not available\n", v); + case VIDIOC_INT_S_VIDEO_ROUTING: + if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) { + v4l_dbg(1, debug, client, "input=%d not available\n", route->input); return -EINVAL; } - if (decoder->input != v) { - saa7110_selmux(client, v); - v4l_dbg(1, debug, client, "switched to input=%d\n", v); + if (decoder->input != route->input) { + saa7110_selmux(client, route->input); + v4l_dbg(1, debug, client, "switched to input=%d\n", route->input); } break; - case DECODER_SET_OUTPUT: - v = *(int *) arg; - /* not much choice of outputs */ - if (v != 0) - return -EINVAL; - break; - - case DECODER_ENABLE_OUTPUT: - v = *(int *) arg; + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + v = cmd == VIDIOC_STREAMON; if (decoder->enable != v) { decoder->enable = v; saa7110_write(client, 0x0E, v ? 0x18 : 0x80); @@ -354,46 +323,79 @@ saa7110_command (struct i2c_client *client, } break; - case DECODER_SET_PICTURE: + case VIDIOC_QUERYCTRL: { - struct video_picture *pic = arg; - - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - saa7110_write(client, 0x19, decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 127 we get 0-65535 */ - decoder->contrast = pic->contrast; - saa7110_write(client, 0x13, - decoder->contrast >> 9); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 127 we get 0-65535 */ - decoder->sat = pic->colour; - saa7110_write(client, 0x12, decoder->sat >> 9); + struct v4l2_queryctrl *qc = arg; + + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill_std(qc); + default: + return -EINVAL; } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - saa7110_write(client, 0x07, - (decoder->hue >> 8) - 128); + break; + } + + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; + break; + default: + return -EINVAL; } break; } - case DECODER_DUMP: - if (!debug) + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + saa7110_write(client, 0x19, decoder->bright); + } break; - for (v = 0; v < SAA7110_NR_REG; v += 16) { - int j; - v4l_dbg(1, debug, client, "%02x:", v); - for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++) - printk(KERN_CONT " %02x", decoder->reg[v + j]); - printk(KERN_CONT "\n"); + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + decoder->contrast = ctrl->value; + saa7110_write(client, 0x13, decoder->contrast); + } + break; + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + saa7110_write(client, 0x12, decoder->sat); + } + break; + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + saa7110_write(client, 0x07, decoder->hue); + } + break; + default: + return -EINVAL; } break; + } default: v4l_dbg(1, debug, client, "unknown command %08x\n", cmd); @@ -430,7 +432,7 @@ static int saa7110_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); if (!decoder) return -ENOMEM; - decoder->norm = VIDEO_MODE_PAL; + decoder->norm = V4L2_STD_PAL; decoder->input = 0; decoder->enable = 1; decoder->bright = 32768; diff --git a/linux/drivers/media/video/saa7111.c b/linux/drivers/media/video/saa7111.c deleted file mode 100644 index 94e5d0b4e..000000000 --- a/linux/drivers/media/video/saa7111.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * saa7111 - Philips SAA7111A video decoder driver version 0.0.3 - * - * Copyright (C) 1998 Dave Perks - * - * Slight changes for video timing and attachment output by - * Wolfgang Scherr - * - * Changes by Ronald Bultje - * - moved over to linux>=2.4.x i2c protocol (1/1/2003) - * - * Changes by Michael Hunold - * - implemented DECODER_SET_GPIO, DECODER_INIT, DECODER_SET_VBI_BYPASS - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "compat.h" - -MODULE_DESCRIPTION("Philips SAA7111 video decoder driver"); -MODULE_AUTHOR("Dave Perks"); -MODULE_LICENSE("GPL"); - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0-1)"); - -/* ----------------------------------------------------------------------- */ - -#define SAA7111_NR_REG 0x18 - -struct saa7111 { - unsigned char reg[SAA7111_NR_REG]; - - int norm; - int input; - int enable; -}; - -/* ----------------------------------------------------------------------- */ - -static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value) -{ - struct saa7111 *decoder = i2c_get_clientdata(client); - - decoder->reg[reg] = value; - return i2c_smbus_write_byte_data(client, reg, value); -} - -static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) -{ - struct saa7111 *decoder = i2c_get_clientdata(client); - - if (decoder->reg[reg] != value) { - decoder->reg[reg] = value; - i2c_smbus_write_byte_data(client, reg, value); - } -} - -static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len) -{ - int ret = -1; - u8 reg; - - /* the saa7111 has an autoincrement function, use it if - * the adapter understands raw I2C */ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ - struct saa7111 *decoder = i2c_get_clientdata(client); - u8 block_data[32]; - int block_len; - - while (len >= 2) { - block_len = 0; - block_data[block_len++] = reg = data[0]; - do { - block_data[block_len++] = - decoder->reg[reg++] = data[1]; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && block_len < 32); - ret = i2c_master_send(client, block_data, block_len); - if (ret < 0) - break; - } - } else { - /* do some slow I2C emulation kind of thing */ - while (len >= 2) { - reg = *data++; - ret = saa7111_write(client, reg, *data++); - if (ret < 0) - break; - len -= 2; - } - } - - return ret; -} - -static int saa7111_init_decoder(struct i2c_client *client, - struct video_decoder_init *init) -{ - return saa7111_write_block(client, init->data, init->len); -} - -static inline int saa7111_read(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -/* ----------------------------------------------------------------------- */ - -static const unsigned char saa7111_i2c_init[] = { - 0x00, 0x00, /* 00 - ID byte */ - 0x01, 0x00, /* 01 - reserved */ - - /*front end */ - 0x02, 0xd0, /* 02 - FUSE=3, GUDL=2, MODE=0 */ - 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, - * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ - 0x04, 0x00, /* 04 - GAI1=256 */ - 0x05, 0x00, /* 05 - GAI2=256 */ - - /* decoder */ - 0x06, 0xf3, /* 06 - HSB at 13(50Hz) / 17(60Hz) - * pixels after end of last line */ - /*0x07, 0x13, * 07 - HSS at 113(50Hz) / 117(60Hz) pixels - * after end of last line */ - 0x07, 0xe8, /* 07 - HSS seems to be needed to - * work with NTSC, too */ - 0x08, 0xc8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, - * VTRC=1, HPLL=0, VNOI=0 */ - 0x09, 0x01, /* 09 - BYPS=0, PREF=0, BPSS=0, - * VBLB=0, UPTCV=0, APER=1 */ - 0x0a, 0x80, /* 0a - BRIG=128 */ - 0x0b, 0x47, /* 0b - CONT=1.109 */ - 0x0c, 0x40, /* 0c - SATN=1.0 */ - 0x0d, 0x00, /* 0d - HUE=0 */ - 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, - * FCTC=0, CHBW=1 */ - 0x0f, 0x00, /* 0f - reserved */ - 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */ - 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, - * OEYC=1, OEHV=1, VIPB=0, COLO=0 */ - 0x12, 0x00, /* 12 - output control 2 */ - 0x13, 0x00, /* 13 - output control 3 */ - 0x14, 0x00, /* 14 - reserved */ - 0x15, 0x00, /* 15 - VBI */ - 0x16, 0x00, /* 16 - VBI */ - 0x17, 0x00, /* 17 - VBI */ -}; - -static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - struct saa7111 *decoder = i2c_get_clientdata(client); - - switch (cmd) { - case 0: - break; - case DECODER_INIT: - { - struct video_decoder_init *init = arg; - struct video_decoder_init vdi; - - if (NULL != init) - return saa7111_init_decoder(client, init); - vdi.data = saa7111_i2c_init; - vdi.len = sizeof(saa7111_i2c_init); - return saa7111_init_decoder(client, &vdi); - } - - case DECODER_DUMP: - { - int i; - - for (i = 0; i < SAA7111_NR_REG; i += 16) { - int j; - - v4l_info(client, "%03x", i); - for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { - printk(KERN_CONT " %02x", - saa7111_read(client, i + j)); - } - printk(KERN_CONT "\n"); - } - break; - } - - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | - VIDEO_DECODER_AUTO | - VIDEO_DECODER_CCIR; - cap->inputs = 8; - cap->outputs = 1; - break; - } - - case DECODER_GET_STATUS: - { - int *iarg = arg; - int status; - int res; - - status = saa7111_read(client, 0x1f); - v4l_dbg(1, debug, client, "status: 0x%02x\n", status); - res = 0; - if ((status & (1 << 6)) == 0) { - res |= DECODER_STATUS_GOOD; - } - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - case VIDEO_MODE_SECAM: - res |= DECODER_STATUS_SECAM; - break; - default: - case VIDEO_MODE_AUTO: - if ((status & (1 << 5)) != 0) { - res |= DECODER_STATUS_NTSC; - } else { - res |= DECODER_STATUS_PAL; - } - break; - } - if ((status & (1 << 0)) != 0) { - res |= DECODER_STATUS_COLOR; - } - *iarg = res; - break; - } - - case DECODER_SET_GPIO: - { - int *iarg = arg; - if (0 != *iarg) { - saa7111_write(client, 0x11, - (decoder->reg[0x11] | 0x80)); - } else { - saa7111_write(client, 0x11, - (decoder->reg[0x11] & 0x7f)); - } - break; - } - - case DECODER_SET_VBI_BYPASS: - { - int *iarg = arg; - if (0 != *iarg) { - saa7111_write(client, 0x13, - (decoder->reg[0x13] & 0xf0) | 0x0a); - } else { - saa7111_write(client, 0x13, - (decoder->reg[0x13] & 0xf0)); - } - break; - } - - case DECODER_SET_NORM: - { - int *iarg = arg; - - switch (*iarg) { - - case VIDEO_MODE_NTSC: - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0x3f) | 0x40); - saa7111_write(client, 0x0e, - (decoder->reg[0x0e] & 0x8f)); - break; - - case VIDEO_MODE_PAL: - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0x3f) | 0x00); - saa7111_write(client, 0x0e, - (decoder->reg[0x0e] & 0x8f)); - break; - - case VIDEO_MODE_SECAM: - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0x3f) | 0x00); - saa7111_write(client, 0x0e, - (decoder->reg[0x0e] & 0x8f) | 0x50); - break; - - case VIDEO_MODE_AUTO: - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0x3f) | 0x80); - saa7111_write(client, 0x0e, - (decoder->reg[0x0e] & 0x8f)); - break; - - default: - return -EINVAL; - - } - decoder->norm = *iarg; - break; - } - - case DECODER_SET_INPUT: - { - int *iarg = arg; - - if (*iarg < 0 || *iarg > 7) { - return -EINVAL; - } - - if (decoder->input != *iarg) { - decoder->input = *iarg; - /* select mode */ - saa7111_write(client, 0x02, - (decoder-> - reg[0x02] & 0xf8) | decoder->input); - /* bypass chrominance trap for modes 4..7 */ - saa7111_write(client, 0x09, - (decoder-> - reg[0x09] & 0x7f) | ((decoder-> - input > - 3) ? 0x80 : - 0)); - } - break; - } - - case DECODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } - break; - } - - case DECODER_ENABLE_OUTPUT: - { - int *iarg = arg; - int enable = (*iarg != 0); - - if (decoder->enable != enable) { - decoder->enable = enable; - - /* RJ: If output should be disabled (for - * playing videos), we also need a open PLL. - * The input is set to 0 (where no input - * source is connected), although this - * is not necessary. - * - * If output should be enabled, we have to - * reverse the above. - */ - - if (decoder->enable) { - saa7111_write(client, 0x02, - (decoder-> - reg[0x02] & 0xf8) | - decoder->input); - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0xfb)); - saa7111_write(client, 0x11, - (decoder-> - reg[0x11] & 0xf3) | 0x0c); - } else { - saa7111_write(client, 0x02, - (decoder->reg[0x02] & 0xf8)); - saa7111_write(client, 0x08, - (decoder-> - reg[0x08] & 0xfb) | 0x04); - saa7111_write(client, 0x11, - (decoder->reg[0x11] & 0xf3)); - } - } - break; - } - - case DECODER_SET_PICTURE: - { - struct video_picture *pic = arg; - - /* We want 0 to 255 we get 0-65535 */ - saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8); - /* We want 0 to 127 we get 0-65535 */ - saa7111_write(client, 0x0b, pic->contrast >> 9); - /* We want 0 to 127 we get 0-65535 */ - saa7111_write(client, 0x0c, pic->colour >> 9); - /* We want -128 to 127 we get 0-65535 */ - saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8); - break; - } - - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - -static int saa7111_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int i; - struct saa7111 *decoder; - struct video_decoder_init vdi; - - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - v4l_info(client, "chip found @ 0x%x (%s)\n", - client->addr << 1, client->adapter->name); - - decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL); - if (decoder == NULL) { - kfree(client); - return -ENOMEM; - } - decoder->norm = VIDEO_MODE_NTSC; - decoder->input = 0; - decoder->enable = 1; - i2c_set_clientdata(client, decoder); - - vdi.data = saa7111_i2c_init; - vdi.len = sizeof(saa7111_i2c_init); - i = saa7111_init_decoder(client, &vdi); - if (i < 0) { - v4l_dbg(1, debug, client, "init status %d\n", i); - } else { - v4l_dbg(1, debug, client, "revision %x\n", - saa7111_read(client, 0x00) >> 4); - } - return 0; -} - -static int saa7111_remove(struct i2c_client *client) -{ - kfree(i2c_get_clientdata(client)); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -static const struct i2c_device_id saa7111_id[] = { - { "saa7111_old", 0 }, /* "saa7111" maps to the saa7115 driver */ - { } -}; -MODULE_DEVICE_TABLE(i2c, saa7111_id); - -#endif -static struct v4l2_i2c_driver_data v4l2_i2c_data = { - .name = "saa7111", - .driverid = I2C_DRIVERID_SAA7111A, - .command = saa7111_command, - .probe = saa7111_probe, - .remove = saa7111_remove, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - .id_table = saa7111_id, -#endif -}; diff --git a/linux/drivers/media/video/saa7114.c b/linux/drivers/media/video/saa7114.c deleted file mode 100644 index 6d380e255..000000000 --- a/linux/drivers/media/video/saa7114.c +++ /dev/null @@ -1,1073 +0,0 @@ -/* - * saa7114 - Philips SAA7114H video decoder driver version 0.0.1 - * - * Copyright (C) 2002 Maxim Yevtyushkin - * - * Based on saa7111 driver by Dave Perks - * - * Copyright (C) 1998 Dave Perks - * - * Slight changes for video timing and attachment output by - * Wolfgang Scherr - * - * Changes by Ronald Bultje - * - moved over to linux>=2.4.x i2c protocol (1/1/2003) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "compat.h" - -MODULE_DESCRIPTION("Philips SAA7114H video decoder driver"); -MODULE_AUTHOR("Maxim Yevtyushkin"); -MODULE_LICENSE("GPL"); - -static int debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0-1)"); - -/* ----------------------------------------------------------------------- */ - -struct saa7114 { - unsigned char reg[0xf0 * 2]; - - int norm; - int input; - int enable; - int bright; - int contrast; - int hue; - int sat; - int playback; -}; - -#define I2C_DELAY 10 - - -//#define SAA_7114_NTSC_HSYNC_START (-3) -//#define SAA_7114_NTSC_HSYNC_STOP (-18) - -#define SAA_7114_NTSC_HSYNC_START (-17) -#define SAA_7114_NTSC_HSYNC_STOP (-32) - -//#define SAA_7114_NTSC_HOFFSET (5) -#define SAA_7114_NTSC_HOFFSET (6) -#define SAA_7114_NTSC_VOFFSET (10) -#define SAA_7114_NTSC_WIDTH (720) -#define SAA_7114_NTSC_HEIGHT (250) - -#define SAA_7114_SECAM_HSYNC_START (-17) -#define SAA_7114_SECAM_HSYNC_STOP (-32) - -#define SAA_7114_SECAM_HOFFSET (2) -#define SAA_7114_SECAM_VOFFSET (10) -#define SAA_7114_SECAM_WIDTH (720) -#define SAA_7114_SECAM_HEIGHT (300) - -#define SAA_7114_PAL_HSYNC_START (-17) -#define SAA_7114_PAL_HSYNC_STOP (-32) - -#define SAA_7114_PAL_HOFFSET (2) -#define SAA_7114_PAL_VOFFSET (10) -#define SAA_7114_PAL_WIDTH (720) -#define SAA_7114_PAL_HEIGHT (300) - - - -#define SAA_7114_VERTICAL_CHROMA_OFFSET 0 //0x50504040 -#define SAA_7114_VERTICAL_LUMA_OFFSET 0 - -#define REG_ADDR(x) (((x) << 1) + 1) -#define LOBYTE(x) ((unsigned char)((x) & 0xff)) -#define HIBYTE(x) ((unsigned char)(((x) >> 8) & 0xff)) -#define LOWORD(x) ((unsigned short int)((x) & 0xffff)) -#define HIWORD(x) ((unsigned short int)(((x) >> 16) & 0xffff)) - - -/* ----------------------------------------------------------------------- */ - -static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len) -{ - int ret = -1; - u8 reg; - - /* the saa7114 has an autoincrement function, use it if - * the adapter understands raw I2C */ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ - u8 block_data[32]; - int block_len; - - while (len >= 2) { - block_len = 0; - block_data[block_len++] = reg = data[0]; - do { - block_data[block_len++] = data[1]; - reg++; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && block_len < 32); - ret = i2c_master_send(client, block_data, block_len); - if (ret < 0) - break; - } - } else { - /* do some slow I2C emulation kind of thing */ - while (len >= 2) { - reg = *data++; - ret = saa7114_write(client, reg, *data++); - if (ret < 0) - break; - len -= 2; - } - } - - return ret; -} - -static inline int saa7114_read(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -/* ----------------------------------------------------------------------- */ - -// initially set NTSC, composite - - -static const unsigned char init[] = { - 0x00, 0x00, /* 00 - ID byte , chip version, - * read only */ - 0x01, 0x08, /* 01 - X,X,X,X, IDEL3 to IDEL0 - - * horizontal increment delay, - * recommended position */ - 0x02, 0x00, /* 02 - FUSE=3, GUDL=2, MODE=0 ; - * input control */ - 0x03, 0x10, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, - * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ - 0x04, 0x90, /* 04 - GAI1=256 */ - 0x05, 0x90, /* 05 - GAI2=256 */ - 0x06, SAA_7114_NTSC_HSYNC_START, /* 06 - HSB: hsync start, - * depends on the video standard */ - 0x07, SAA_7114_NTSC_HSYNC_STOP, /* 07 - HSS: hsync stop, depends - *on the video standard */ - 0x08, 0xb8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1, - * HPLL: free running in playback, locked - * in capture, VNOI=0 */ - 0x09, 0x80, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0, - * UPTCV=0, APER=1; depends from input */ - 0x0a, 0x80, /* 0a - BRIG=128 */ - 0x0b, 0x44, /* 0b - CONT=1.109 */ - 0x0c, 0x40, /* 0c - SATN=1.0 */ - 0x0d, 0x00, /* 0d - HUE=0 */ - 0x0e, 0x84, /* 0e - CDTO, CSTD2 to 0, DCVF, FCTC, - * CCOMB; depends from video standard */ - 0x0f, 0x24, /* 0f - ACGC,CGAIN6 to CGAIN0; depends - * from video standard */ - 0x10, 0x03, /* 10 - OFFU1 to 0, OFFV1 to 0, CHBW, - * LCBW2 to 0 */ - 0x11, 0x59, /* 11 - COLO, RTP1, HEDL1 to 0, RTP0, - * YDEL2 to 0 */ - 0x12, 0xc9, /* 12 - RT signal control RTSE13 to 10 - * and 03 to 00 */ - 0x13, 0x80, /* 13 - RT/X port output control */ - 0x14, 0x00, /* 14 - analog, ADC, compatibility control */ - 0x15, 0x00, /* 15 - VGATE start FID change */ - 0x16, 0xfe, /* 16 - VGATE stop */ - 0x17, 0x00, /* 17 - Misc., VGATE MSBs */ - 0x18, 0x40, /* RAWG */ - 0x19, 0x80, /* RAWO */ - 0x1a, 0x00, - 0x1b, 0x00, - 0x1c, 0x00, - 0x1d, 0x00, - 0x1e, 0x00, - 0x1f, 0x00, /* status byte, read only */ - 0x20, 0x00, /* video decoder reserved part */ - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x24, 0x00, - 0x25, 0x00, - 0x26, 0x00, - 0x27, 0x00, - 0x28, 0x00, - 0x29, 0x00, - 0x2a, 0x00, - 0x2b, 0x00, - 0x2c, 0x00, - 0x2d, 0x00, - 0x2e, 0x00, - 0x2f, 0x00, - 0x30, 0xbc, /* audio clock generator */ - 0x31, 0xdf, - 0x32, 0x02, - 0x33, 0x00, - 0x34, 0xcd, - 0x35, 0xcc, - 0x36, 0x3a, - 0x37, 0x00, - 0x38, 0x03, - 0x39, 0x10, - 0x3a, 0x00, - 0x3b, 0x00, - 0x3c, 0x00, - 0x3d, 0x00, - 0x3e, 0x00, - 0x3f, 0x00, - 0x40, 0x00, /* VBI data slicer */ - 0x41, 0xff, - 0x42, 0xff, - 0x43, 0xff, - 0x44, 0xff, - 0x45, 0xff, - 0x46, 0xff, - 0x47, 0xff, - 0x48, 0xff, - 0x49, 0xff, - 0x4a, 0xff, - 0x4b, 0xff, - 0x4c, 0xff, - 0x4d, 0xff, - 0x4e, 0xff, - 0x4f, 0xff, - 0x50, 0xff, - 0x51, 0xff, - 0x52, 0xff, - 0x53, 0xff, - 0x54, 0xff, - 0x55, 0xff, - 0x56, 0xff, - 0x57, 0xff, - 0x58, 0x40, // framing code - 0x59, 0x47, // horizontal offset - 0x5a, 0x06, // vertical offset - 0x5b, 0x83, // field offset - 0x5c, 0x00, // reserved - 0x5d, 0x3e, // header and data - 0x5e, 0x00, // sliced data - 0x5f, 0x00, // reserved - 0x60, 0x00, /* video decoder reserved part */ - 0x61, 0x00, - 0x62, 0x00, - 0x63, 0x00, - 0x64, 0x00, - 0x65, 0x00, - 0x66, 0x00, - 0x67, 0x00, - 0x68, 0x00, - 0x69, 0x00, - 0x6a, 0x00, - 0x6b, 0x00, - 0x6c, 0x00, - 0x6d, 0x00, - 0x6e, 0x00, - 0x6f, 0x00, - 0x70, 0x00, /* video decoder reserved part */ - 0x71, 0x00, - 0x72, 0x00, - 0x73, 0x00, - 0x74, 0x00, - 0x75, 0x00, - 0x76, 0x00, - 0x77, 0x00, - 0x78, 0x00, - 0x79, 0x00, - 0x7a, 0x00, - 0x7b, 0x00, - 0x7c, 0x00, - 0x7d, 0x00, - 0x7e, 0x00, - 0x7f, 0x00, - 0x80, 0x00, /* X-port, I-port and scaler */ - 0x81, 0x00, - 0x82, 0x00, - 0x83, 0x00, - 0x84, 0xc5, - 0x85, 0x0d, // hsync and vsync ? - 0x86, 0x40, - 0x87, 0x01, - 0x88, 0x00, - 0x89, 0x00, - 0x8a, 0x00, - 0x8b, 0x00, - 0x8c, 0x00, - 0x8d, 0x00, - 0x8e, 0x00, - 0x8f, 0x00, - 0x90, 0x03, /* Task A definition */ - 0x91, 0x08, - 0x92, 0x00, - 0x93, 0x40, - 0x94, 0x00, // window settings - 0x95, 0x00, - 0x96, 0x00, - 0x97, 0x00, - 0x98, 0x00, - 0x99, 0x00, - 0x9a, 0x00, - 0x9b, 0x00, - 0x9c, 0x00, - 0x9d, 0x00, - 0x9e, 0x00, - 0x9f, 0x00, - 0xa0, 0x01, /* horizontal integer prescaling ratio */ - 0xa1, 0x00, /* horizontal prescaler accumulation - * sequence length */ - 0xa2, 0x00, /* UV FIR filter, Y FIR filter, prescaler - * DC gain */ - 0xa3, 0x00, - 0xa4, 0x80, // luminance brightness - 0xa5, 0x40, // luminance gain - 0xa6, 0x40, // chrominance saturation - 0xa7, 0x00, - 0xa8, 0x00, // horizontal luminance scaling increment - 0xa9, 0x04, - 0xaa, 0x00, // horizontal luminance phase offset - 0xab, 0x00, - 0xac, 0x00, // horizontal chrominance scaling increment - 0xad, 0x02, - 0xae, 0x00, // horizontal chrominance phase offset - 0xaf, 0x00, - 0xb0, 0x00, // vertical luminance scaling increment - 0xb1, 0x04, - 0xb2, 0x00, // vertical chrominance scaling increment - 0xb3, 0x04, - 0xb4, 0x00, - 0xb5, 0x00, - 0xb6, 0x00, - 0xb7, 0x00, - 0xb8, 0x00, - 0xb9, 0x00, - 0xba, 0x00, - 0xbb, 0x00, - 0xbc, 0x00, - 0xbd, 0x00, - 0xbe, 0x00, - 0xbf, 0x00, - 0xc0, 0x02, // Task B definition - 0xc1, 0x08, - 0xc2, 0x00, - 0xc3, 0x40, - 0xc4, 0x00, // window settings - 0xc5, 0x00, - 0xc6, 0x00, - 0xc7, 0x00, - 0xc8, 0x00, - 0xc9, 0x00, - 0xca, 0x00, - 0xcb, 0x00, - 0xcc, 0x00, - 0xcd, 0x00, - 0xce, 0x00, - 0xcf, 0x00, - 0xd0, 0x01, // horizontal integer prescaling ratio - 0xd1, 0x00, // horizontal prescaler accumulation sequence length - 0xd2, 0x00, // UV FIR filter, Y FIR filter, prescaler DC gain - 0xd3, 0x00, - 0xd4, 0x80, // luminance brightness - 0xd5, 0x40, // luminance gain - 0xd6, 0x40, // chrominance saturation - 0xd7, 0x00, - 0xd8, 0x00, // horizontal luminance scaling increment - 0xd9, 0x04, - 0xda, 0x00, // horizontal luminance phase offset - 0xdb, 0x00, - 0xdc, 0x00, // horizontal chrominance scaling increment - 0xdd, 0x02, - 0xde, 0x00, // horizontal chrominance phase offset - 0xdf, 0x00, - 0xe0, 0x00, // vertical luminance scaling increment - 0xe1, 0x04, - 0xe2, 0x00, // vertical chrominance scaling increment - 0xe3, 0x04, - 0xe4, 0x00, - 0xe5, 0x00, - 0xe6, 0x00, - 0xe7, 0x00, - 0xe8, 0x00, - 0xe9, 0x00, - 0xea, 0x00, - 0xeb, 0x00, - 0xec, 0x00, - 0xed, 0x00, - 0xee, 0x00, - 0xef, 0x00 -}; - -static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - struct saa7114 *decoder = i2c_get_clientdata(client); - - switch (cmd) { - case 0: - //dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client)); - //saa7114_write_block(client, init, sizeof(init)); - break; - - case DECODER_DUMP: - { - int i; - - if (!debug) - break; - v4l_info(client, "decoder dump\n"); - - for (i = 0; i < 32; i += 16) { - int j; - - v4l_info(client, "%03x", i); - for (j = 0; j < 16; ++j) { - printk(KERN_CONT " %02x", - saa7114_read(client, i + j)); - } - printk(KERN_CONT "\n"); - } - break; - } - - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - v4l_dbg(1, debug, client, "get capabilities\n"); - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_AUTO | - VIDEO_DECODER_CCIR; - cap->inputs = 8; - cap->outputs = 1; - break; - } - - case DECODER_GET_STATUS: - { - int *iarg = arg; - int status; - int res; - - status = saa7114_read(client, 0x1f); - - v4l_dbg(1, debug, client, "status: 0x%02x\n", status); - res = 0; - if ((status & (1 << 6)) == 0) { - res |= DECODER_STATUS_GOOD; - } - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - case VIDEO_MODE_SECAM: - res |= DECODER_STATUS_SECAM; - break; - default: - case VIDEO_MODE_AUTO: - if ((status & (1 << 5)) != 0) { - res |= DECODER_STATUS_NTSC; - } else { - res |= DECODER_STATUS_PAL; - } - break; - } - if ((status & (1 << 0)) != 0) { - res |= DECODER_STATUS_COLOR; - } - *iarg = res; - break; - } - - case DECODER_SET_NORM: - { - int *iarg = arg; - - short int hoff = 0, voff = 0, w = 0, h = 0; - - v4l_dbg(1, debug, client, "set norm\n"); - - switch (*iarg) { - case VIDEO_MODE_NTSC: - v4l_dbg(1, debug, client, "NTSC\n"); - decoder->reg[REG_ADDR(0x06)] = - SAA_7114_NTSC_HSYNC_START; - decoder->reg[REG_ADDR(0x07)] = - SAA_7114_NTSC_HSYNC_STOP; - - decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture - - decoder->reg[REG_ADDR(0x0e)] = 0x85; - decoder->reg[REG_ADDR(0x0f)] = 0x24; - - hoff = SAA_7114_NTSC_HOFFSET; - voff = SAA_7114_NTSC_VOFFSET; - w = SAA_7114_NTSC_WIDTH; - h = SAA_7114_NTSC_HEIGHT; - - break; - - case VIDEO_MODE_PAL: - v4l_dbg(1, debug, client, "PAL\n"); - decoder->reg[REG_ADDR(0x06)] = - SAA_7114_PAL_HSYNC_START; - decoder->reg[REG_ADDR(0x07)] = - SAA_7114_PAL_HSYNC_STOP; - - decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture - - decoder->reg[REG_ADDR(0x0e)] = 0x81; - decoder->reg[REG_ADDR(0x0f)] = 0x24; - - hoff = SAA_7114_PAL_HOFFSET; - voff = SAA_7114_PAL_VOFFSET; - w = SAA_7114_PAL_WIDTH; - h = SAA_7114_PAL_HEIGHT; - - break; - - default: - v4l_dbg(1, debug, client, "Unknown video mode\n"); - return -EINVAL; - } - - - decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low - decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high - decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low - decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high - decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low - decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high - decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low - decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high - decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low - decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high - decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low - decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high - - decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low - decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high - decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low - decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high - decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low - decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high - decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low - decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high - decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low - decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high - decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low - decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high - - - saa7114_write(client, 0x80, 0x06); // i-port and scaler back end clock selection, task A&B off - saa7114_write(client, 0x88, 0xd8); // sw reset scaler - saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - - saa7114_write_block(client, decoder->reg + (0x06 << 1), - 3 << 1); - saa7114_write_block(client, decoder->reg + (0x0e << 1), - 2 << 1); - saa7114_write_block(client, decoder->reg + (0x5a << 1), - 2 << 1); - - saa7114_write_block(client, decoder->reg + (0x94 << 1), - (0x9f + 1 - 0x94) << 1); - saa7114_write_block(client, decoder->reg + (0xc4 << 1), - (0xcf + 1 - 0xc4) << 1); - - saa7114_write(client, 0x88, 0xd8); // sw reset scaler - saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection - - decoder->norm = *iarg; - break; - } - - case DECODER_SET_INPUT: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set input (%d)\n", *iarg); - if (*iarg < 0 || *iarg > 7) { - return -EINVAL; - } - - if (decoder->input != *iarg) { - v4l_dbg(1, debug, client, "now setting %s input\n", - *iarg >= 6 ? "S-Video" : "Composite"); - decoder->input = *iarg; - - /* select mode */ - decoder->reg[REG_ADDR(0x02)] = - (decoder-> - reg[REG_ADDR(0x02)] & 0xf0) | (decoder-> - input < - 6 ? 0x0 : 0x9); - saa7114_write(client, 0x02, - decoder->reg[REG_ADDR(0x02)]); - - /* bypass chrominance trap for modes 6..9 */ - decoder->reg[REG_ADDR(0x09)] = - (decoder-> - reg[REG_ADDR(0x09)] & 0x7f) | (decoder-> - input < - 6 ? 0x0 : - 0x80); - saa7114_write(client, 0x09, - decoder->reg[REG_ADDR(0x09)]); - - decoder->reg[REG_ADDR(0x0e)] = - decoder->input < - 6 ? decoder-> - reg[REG_ADDR(0x0e)] | 1 : decoder-> - reg[REG_ADDR(0x0e)] & ~1; - saa7114_write(client, 0x0e, - decoder->reg[REG_ADDR(0x0e)]); - } - break; - } - - case DECODER_SET_OUTPUT: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set output\n"); - - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } - break; - } - - case DECODER_ENABLE_OUTPUT: - { - int *iarg = arg; - int enable = (*iarg != 0); - - v4l_dbg(1, debug, client, "%s output\n", - enable ? "enable" : "disable"); - - decoder->playback = !enable; - - if (decoder->enable != enable) { - decoder->enable = enable; - - /* RJ: If output should be disabled (for - * playing videos), we also need a open PLL. - * The input is set to 0 (where no input - * source is connected), although this - * is not necessary. - * - * If output should be enabled, we have to - * reverse the above. - */ - - if (decoder->enable) { - decoder->reg[REG_ADDR(0x08)] = 0xb8; - decoder->reg[REG_ADDR(0x12)] = 0xc9; - decoder->reg[REG_ADDR(0x13)] = 0x80; - decoder->reg[REG_ADDR(0x87)] = 0x01; - } else { - decoder->reg[REG_ADDR(0x08)] = 0x7c; - decoder->reg[REG_ADDR(0x12)] = 0x00; - decoder->reg[REG_ADDR(0x13)] = 0x00; - decoder->reg[REG_ADDR(0x87)] = 0x00; - } - - saa7114_write_block(client, - decoder->reg + (0x12 << 1), - 2 << 1); - saa7114_write(client, 0x08, - decoder->reg[REG_ADDR(0x08)]); - saa7114_write(client, 0x87, - decoder->reg[REG_ADDR(0x87)]); - saa7114_write(client, 0x88, 0xd8); // sw reset scaler - saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - saa7114_write(client, 0x80, 0x36); - - } - break; - } - - case DECODER_SET_PICTURE: - { - struct video_picture *pic = arg; - - v4l_dbg(1, debug, client, - "decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n", - pic->brightness, pic->contrast, pic->colour, pic->hue); - - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - saa7114_write(client, 0x0a, decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 127 we get 0-65535 */ - decoder->contrast = pic->contrast; - saa7114_write(client, 0x0b, - decoder->contrast >> 9); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 127 we get 0-65535 */ - decoder->sat = pic->colour; - saa7114_write(client, 0x0c, decoder->sat >> 9); - } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - saa7114_write(client, 0x0d, - (decoder->hue - 32768) >> 8); - } - break; - } - - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - -static int saa7114_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int i, err[30]; - short int hoff = SAA_7114_NTSC_HOFFSET; - short int voff = SAA_7114_NTSC_VOFFSET; - short int w = SAA_7114_NTSC_WIDTH; - short int h = SAA_7114_NTSC_HEIGHT; - struct saa7114 *decoder; - - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - v4l_info(client, "chip found @ 0x%x (%s)\n", - client->addr << 1, client->adapter->name); - - decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL); - if (decoder == NULL) - return -ENOMEM; - decoder->norm = VIDEO_MODE_NTSC; - decoder->input = -1; - decoder->enable = 1; - decoder->bright = 32768; - decoder->contrast = 32768; - decoder->hue = 32768; - decoder->sat = 32768; - decoder->playback = 0; // initially capture mode useda - i2c_set_clientdata(client, decoder); - - memcpy(decoder->reg, init, sizeof(init)); - - decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low - decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high - decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low - decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high - decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low - decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high - decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low - decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high - decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low - decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high - decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low - decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high - - decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low - decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high - decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low - decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high - decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low - decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high - decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low - decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high - decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low - decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high - decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low - decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high - - decoder->reg[REG_ADDR(0xb8)] = - LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xb9)] = - HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xba)] = - LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xbb)] = - HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - - decoder->reg[REG_ADDR(0xbc)] = - LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xbd)] = - HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xbe)] = - LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xbf)] = - HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - - decoder->reg[REG_ADDR(0xe8)] = - LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xe9)] = - HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xea)] = - LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xeb)] = - HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - - decoder->reg[REG_ADDR(0xec)] = - LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xed)] = - HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xee)] = - LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xef)] = - HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - - - decoder->reg[REG_ADDR(0x13)] = 0x80; // RTC0 on - decoder->reg[REG_ADDR(0x87)] = 0x01; // I-Port - decoder->reg[REG_ADDR(0x12)] = 0xc9; // RTS0 - - decoder->reg[REG_ADDR(0x02)] = 0xc0; // set composite1 input, aveasy - decoder->reg[REG_ADDR(0x09)] = 0x00; // chrominance trap - decoder->reg[REG_ADDR(0x0e)] |= 1; // combfilter on - - - v4l_dbg(1, debug, client, "starting init\n"); - - err[0] = - saa7114_write_block(client, decoder->reg + (0x20 << 1), - 0x10 << 1); - err[1] = - saa7114_write_block(client, decoder->reg + (0x30 << 1), - 0x10 << 1); - err[2] = - saa7114_write_block(client, decoder->reg + (0x63 << 1), - (0x7f + 1 - 0x63) << 1); - err[3] = - saa7114_write_block(client, decoder->reg + (0x89 << 1), - 6 << 1); - err[4] = - saa7114_write_block(client, decoder->reg + (0xb8 << 1), - 8 << 1); - err[5] = - saa7114_write_block(client, decoder->reg + (0xe8 << 1), - 8 << 1); - - - for (i = 0; i <= 5; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - for (i = 6; i < 8; i++) { - v4l_dbg(1, debug, client, - "reg[0x%02x] = 0x%02x (0x%02x)\n", - i, saa7114_read(client, i), - decoder->reg[REG_ADDR(i)]); - } - - v4l_dbg(1, debug, client, - "performing decoder reset sequence\n"); - - err[6] = saa7114_write(client, 0x80, 0x06); // i-port and scaler backend clock selection, task A&B off - err[7] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler - err[8] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - - for (i = 6; i <= 8; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - v4l_dbg(1, debug, client, "performing the rest of init\n"); - - err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]); - err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1); // big seq - err[11] = saa7114_write_block(client, decoder->reg + (0x40 << 1), (0x5f + 1 - 0x40) << 1); // slicer - err[12] = saa7114_write_block(client, decoder->reg + (0x81 << 1), 2 << 1); // ? - err[13] = saa7114_write_block(client, decoder->reg + (0x83 << 1), 5 << 1); // ? - err[14] = saa7114_write_block(client, decoder->reg + (0x90 << 1), 4 << 1); // Task A - err[15] = - saa7114_write_block(client, decoder->reg + (0x94 << 1), - 12 << 1); - err[16] = - saa7114_write_block(client, decoder->reg + (0xa0 << 1), - 8 << 1); - err[17] = - saa7114_write_block(client, decoder->reg + (0xa8 << 1), - 8 << 1); - err[18] = - saa7114_write_block(client, decoder->reg + (0xb0 << 1), - 8 << 1); - err[19] = saa7114_write_block(client, decoder->reg + (0xc0 << 1), 4 << 1); // Task B - err[15] = - saa7114_write_block(client, decoder->reg + (0xc4 << 1), - 12 << 1); - err[16] = - saa7114_write_block(client, decoder->reg + (0xd0 << 1), - 8 << 1); - err[17] = - saa7114_write_block(client, decoder->reg + (0xd8 << 1), - 8 << 1); - err[18] = - saa7114_write_block(client, decoder->reg + (0xe0 << 1), - 8 << 1); - - for (i = 9; i <= 18; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - - for (i = 6; i < 8; i++) { - v4l_dbg(1, debug, client, - "reg[0x%02x] = 0x%02x (0x%02x)\n", - i, saa7114_read(client, i), - decoder->reg[REG_ADDR(i)]); - } - - - for (i = 0x11; i <= 0x13; i++) { - v4l_dbg(1, debug, client, - "reg[0x%02x] = 0x%02x (0x%02x)\n", - i, saa7114_read(client, i), - decoder->reg[REG_ADDR(i)]); - } - - - v4l_dbg(1, debug, client, "setting video input\n"); - - err[19] = - saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]); - err[20] = - saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]); - err[21] = - saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]); - - for (i = 19; i <= 21; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - v4l_dbg(1, debug, client, "performing decoder reset sequence\n"); - - err[22] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler - err[23] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - err[24] = saa7114_write(client, 0x80, 0x36); // i-port and scaler backend clock selection, task A&B off - - - for (i = 22; i <= 24; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - err[25] = saa7114_write(client, 0x06, init[REG_ADDR(0x06)]); - err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]); - err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]); - - v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n", - saa7114_read(client, 0x00) >> 4, - saa7114_read(client, 0x1f)); - v4l_dbg(1, debug, client, - "power save control: 0x%02x, scaler status: 0x%02x\n", - saa7114_read(client, 0x88), - saa7114_read(client, 0x8f)); - - - for (i = 0x94; i < 0x96; i++) { - v4l_dbg(1, debug, client, - "reg[0x%02x] = 0x%02x (0x%02x)\n", - i, saa7114_read(client, i), - decoder->reg[REG_ADDR(i)]); - } - - //i = saa7114_write_block(client, init, sizeof(init)); - return 0; -} - -static int saa7114_remove(struct i2c_client *client) -{ - kfree(i2c_get_clientdata(client)); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -static const struct i2c_device_id saa7114_id[] = { - { "saa7114_old", 0 }, /* "saa7114" maps to the saa7115 driver */ - { } -}; -MODULE_DEVICE_TABLE(i2c, saa7114_id); - -#endif -static struct v4l2_i2c_driver_data v4l2_i2c_data = { - .name = "saa7114", - .driverid = I2C_DRIVERID_SAA7114, - .command = saa7114_command, - .probe = saa7114_probe, - .remove = saa7114_remove, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - .id_table = saa7114_id, -#endif -}; diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c index 68bec4d5d..08cc04138 100644 --- a/linux/drivers/media/video/saa7185.c +++ b/linux/drivers/media/video/saa7185.c @@ -50,8 +50,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct saa7185 { unsigned char reg[128]; - int norm; - int enable; + v4l2_std_id norm; int bright; int contrast; int hue; @@ -219,68 +218,43 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) struct saa7185 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: saa7185_write_block(client, init_common, sizeof(init_common)); - switch (encoder->norm) { - - case VIDEO_MODE_NTSC: + if (encoder->norm & V4L2_STD_NTSC) saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); - break; - - case VIDEO_MODE_PAL: + else saa7185_write_block(client, init_pal, sizeof(init_pal)); - break; - } - break; - - case ENCODER_GET_CAPABILITIES: - { - struct video_encoder_capability *cap = arg; - - cap->flags = - VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC | - VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR; - cap->inputs = 1; - cap->outputs = 1; break; - } - case ENCODER_SET_NORM: + case VIDIOC_INT_S_STD_OUTPUT: { - int *iarg = arg; + v4l2_std_id *iarg = arg; //saa7185_write_block(client, init_common, sizeof(init_common)); - switch (*iarg) { - case VIDEO_MODE_NTSC: + if (*iarg & V4L2_STD_NTSC) saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); - break; - - case VIDEO_MODE_PAL: + else if (*iarg & V4L2_STD_PAL) saa7185_write_block(client, init_pal, sizeof(init_pal)); - break; - - case VIDEO_MODE_SECAM: - default: + else return -EINVAL; - } encoder->norm = *iarg; break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg; + struct v4l2_routing *route = arg; - /* RJ: *iarg = 0: input is from SA7111 - *iarg = 1: input is from ZR36060 */ + /* RJ: route->input = 0: input is from SA7111 + route->input = 1: input is from ZR36060 */ - switch (*iarg) { + switch (route->input) { case 0: /* turn off colorbar */ saa7185_write(client, 0x3a, 0x0f); @@ -316,27 +290,6 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; - saa7185_write(client, 0x61, - (encoder->reg[0x61] & 0xbf) | - (encoder->enable ? 0x00 : 0x40)); - break; - } - default: return -EINVAL; } @@ -366,8 +319,7 @@ static int saa7185_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - encoder->norm = VIDEO_MODE_NTSC; - encoder->enable = 1; + encoder->norm = V4L2_STD_NTSC; i2c_set_clientdata(client, encoder); i = saa7185_write_block(client, init_common, sizeof(init_common)); diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index 5f368a1be..2487f8fe2 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "compat.h" @@ -45,7 +46,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct vpx3220 { unsigned char reg[255]; - int norm; + v4l2_std_id norm; int input; int enable; int bright; @@ -260,6 +261,7 @@ static const unsigned short init_fp[] = { 0x4b, 0x298, /* PLL gain */ }; +#if 0 static void vpx3220_dump_i2c(struct i2c_client *client) { int len = sizeof(init_common); @@ -272,67 +274,42 @@ static void vpx3220_dump_i2c(struct i2c_client *client) len -= 2; } } +#endif static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) { struct vpx3220 *decoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: { vpx3220_write_block(client, init_common, sizeof(init_common)); vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); - switch (decoder->norm) { - case VIDEO_MODE_NTSC: + if (decoder->norm & V4L2_STD_NTSC) { vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); - break; - - case VIDEO_MODE_PAL: + } else if (decoder->norm & V4L2_STD_PAL) { vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); - break; - case VIDEO_MODE_SECAM: + } else if (decoder->norm & V4L2_STD_SECAM) { vpx3220_write_fp_block(client, init_secam, sizeof(init_secam) >> 1); - break; - default: + } else { vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); - break; } break; } - case DECODER_DUMP: - { - vpx3220_dump_i2c(client); - break; - } - - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n"); - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | - VIDEO_DECODER_AUTO | - VIDEO_DECODER_CCIR; - cap->inputs = 3; - cap->outputs = 1; - break; - } - - case DECODER_GET_STATUS: + case VIDIOC_QUERYSTD: + case VIDIOC_INT_G_INPUT_STATUS: { - int res = 0, status; + int res = V4L2_IN_ST_NO_SIGNAL, status; + v4l2_std_id std = 0; - v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n"); + v4l_dbg(1, debug, client, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); status = vpx3220_fp_read(client, 0x0f3); @@ -342,35 +319,38 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) return status; if ((status & 0x20) == 0) { - res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR; + res = 0; switch (status & 0x18) { case 0x00: case 0x10: case 0x14: case 0x18: - res |= DECODER_STATUS_PAL; + std = V4L2_STD_PAL; break; case 0x08: - res |= DECODER_STATUS_SECAM; + std = V4L2_STD_SECAM; break; case 0x04: case 0x0c: case 0x1c: - res |= DECODER_STATUS_NTSC; + std = V4L2_STD_NTSC; break; } } - *(int *) arg = res; + if (cmd == VIDIOC_QUERYSTD) + *(v4l2_std_id *)arg = std; + else + *(int *)arg = res; break; } - case DECODER_SET_NORM: + case VIDIOC_S_STD: { - int *iarg = arg, data; + v4l2_std_id *iarg = arg; int temp_input; /* Here we back up the input selection because it gets @@ -378,36 +358,31 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) choosen video norm */ temp_input = vpx3220_fp_read(client, 0xf2); - v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg); - switch (*iarg) { - case VIDEO_MODE_NTSC: + v4l_dbg(1, debug, client, "VIDIOC_S_STD %llx\n", *iarg); + if (*iarg & V4L2_STD_NTSC) { vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); v4l_dbg(1, debug, client, "norm switched to NTSC\n"); - break; - - case VIDEO_MODE_PAL: + } else if (*iarg & V4L2_STD_PAL) { vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); v4l_dbg(1, debug, client, "norm switched to PAL\n"); - break; - - case VIDEO_MODE_SECAM: + } else if (*iarg & V4L2_STD_SECAM) { vpx3220_write_fp_block(client, init_secam, sizeof(init_secam) >> 1); v4l_dbg(1, debug, client, "norm switched to SECAM\n"); - break; + } else { + return -EINVAL; + } +#if 0 case VIDEO_MODE_AUTO: /* FIXME This is only preliminary support */ data = vpx3220_fp_read(client, 0xf2) & 0x20; vpx3220_fp_write(client, 0xf2, 0x00c0 | data); v4l_dbg(1, debug, client, "norm switched to AUTO\n"); break; - - default: - return -EINVAL; - } +#endif decoder->norm = *iarg; /* And here we set the backed up video input again */ @@ -416,9 +391,10 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case DECODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg, data; + struct v4l2_routing *route = arg; + int data; /* RJ: *iarg = 0: ST8 (PCTV) input *iarg = 1: COMPOSITE input @@ -430,73 +406,117 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) {0x0e, 1} }; - if (*iarg < 0 || *iarg > 2) + if (route->input < 0 || route->input > 2) return -EINVAL; - v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]); + v4l_dbg(1, debug, client, "input switched to %s\n", inputs[route->input]); - vpx3220_write(client, 0x33, input[*iarg][0]); + vpx3220_write(client, 0x33, input[route->input][0]); data = vpx3220_fp_read(client, 0xf2) & ~(0x0020); if (data < 0) return data; /* 0x0010 is required to latch the setting */ vpx3220_fp_write(client, 0xf2, - data | (input[*iarg][1] << 5) | 0x0010); + data | (input[route->input][1] << 5) | 0x0010); udelay(10); break; } - case DECODER_SET_OUTPUT: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: { - int *iarg = arg; + int on = cmd == VIDIOC_STREAMON; + v4l_dbg(1, debug, client, "VIDIOC_STREAM%s\n", on ? "ON" : "OFF"); - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } + vpx3220_write(client, 0xf2, (on ? 0x1b : 0x00)); break; } - case DECODER_ENABLE_OUTPUT: + case VIDIOC_QUERYCTRL: { - int *iarg = arg; + struct v4l2_queryctrl *qc = arg; + + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; + + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 63, 1, 32); + break; + + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048); + break; - v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg); + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, -512, 511, 1, 0); + break; - vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00)); + default: + return -EINVAL; + } break; } - case DECODER_SET_PICTURE: + case VIDIOC_G_CTRL: { - struct video_picture *pic = arg; + struct v4l2_control *ctrl = arg; - if (decoder->bright != pic->brightness) { - /* We want -128 to 128 we get 0-65535 */ - decoder->bright = pic->brightness; - vpx3220_write(client, 0xe6, - (decoder->bright - 32768) >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 64 we get 0-65535 */ - /* Bit 7 and 8 is for noise shaping */ - decoder->contrast = pic->contrast; - vpx3220_write(client, 0xe7, - (decoder->contrast >> 10) + 192); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 4096 we get 0-65535 */ - decoder->sat = pic->colour; - vpx3220_fp_write(client, 0xa0, - decoder->sat >> 4); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; + break; + default: + return -EINVAL; } - if (decoder->hue != pic->hue) { - /* We want -512 to 512 we get 0-65535 */ - decoder->hue = pic->hue; - vpx3220_fp_write(client, 0x1c, - ((decoder->hue - 32768) >> 6) & 0xFFF); + break; + } + + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + vpx3220_write(client, 0xe6, decoder->bright); + } + break; + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + /* Bit 7 and 8 is for noise shaping */ + decoder->contrast = ctrl->value; + vpx3220_write(client, 0xe7, + decoder->contrast + 192); + } + break; + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + vpx3220_fp_write(client, 0xa0, decoder->sat); + } + break; + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + vpx3220_fp_write(client, 0x1c, decoder->hue); + } + break; + default: + return -EINVAL; } break; } @@ -542,7 +562,7 @@ static int vpx3220_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; - decoder->norm = VIDEO_MODE_PAL; + decoder->norm = V4L2_STD_PAL; decoder->input = 0; decoder->enable = 1; decoder->bright = 32768; diff --git a/linux/drivers/media/video/zoran/Kconfig b/linux/drivers/media/video/zoran/Kconfig index a0fe52260..925fb5159 100644 --- a/linux/drivers/media/video/zoran/Kconfig +++ b/linux/drivers/media/video/zoran/Kconfig @@ -32,7 +32,7 @@ config VIDEO_ZORAN_ZR36060 config VIDEO_ZORAN_BUZ tristate "Iomega Buz support" depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO help Support for the Iomega Buz MJPEG capture/playback card. @@ -58,7 +58,7 @@ config VIDEO_ZORAN_LML33 config VIDEO_ZORAN_LML33R10 tristate "Linux Media Labs LML33R10 support" depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO help support for the Linux Media Labs LML33R10 MJPEG capture/playback diff --git a/linux/drivers/media/video/zoran/zoran.h b/linux/drivers/media/video/zoran/zoran.h index 76668bda0..ee31bfc34 100644 --- a/linux/drivers/media/video/zoran/zoran.h +++ b/linux/drivers/media/video/zoran/zoran.h @@ -352,7 +352,7 @@ struct card_info { char name[32]; } input[BUZ_MAX_INPUT]; - int norms; + v4l2_std_id norms; struct tvnorm *tvn[3]; /* supported TV norms */ u32 jpeg_int; /* JPEG interrupt */ @@ -401,8 +401,8 @@ struct zoran { spinlock_t spinlock; /* Spinlock */ /* Video for Linux parameters */ - int input, norm; /* card's norm and input - norm=VIDEO_MODE_* */ - int hue, saturation, contrast, brightness; /* Current picture params */ + int input; /* card's norm and input - norm=VIDEO_MODE_* */ + v4l2_std_id norm; struct video_buffer buffer; /* Current buffer params */ struct zoran_overlay_settings overlay_settings; u32 *overlay_mask; /* overlay mask */ diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 552204bab..17c3aaffd 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -341,11 +341,8 @@ i2cid_to_modulename (u16 i2c_id) case I2C_DRIVERID_SAA7110: name = "saa7110"; break; - case I2C_DRIVERID_SAA7111A: - name = "saa7111"; - break; - case I2C_DRIVERID_SAA7114: - name = "saa7114"; + case I2C_DRIVERID_SAA711X: + name = "saa7115"; break; case I2C_DRIVERID_SAA7185B: name = "saa7185"; @@ -440,7 +437,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 2, "S-Video" }, { 0, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel_dc10, &f60sqpixel_dc10, @@ -468,7 +465,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 7, "S-Video" }, { 5, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel, &f60sqpixel, @@ -495,7 +492,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 7, "S-Video" }, { 5, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel, &f60sqpixel, @@ -524,7 +521,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 2, "S-Video" }, { 0, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel_dc10, &f60sqpixel_dc10, @@ -553,7 +550,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 2, "S-Video" }, { 0, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel_dc10, &f60sqpixel_dc10, @@ -580,7 +577,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 0, "Composite" }, { 7, "S-Video" } }, - .norms = 2, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL, .tvn = { &f50ccir601_lml33, &f60ccir601_lml33, @@ -598,7 +595,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = LML33R10, .name = "LML33R10", - .i2c_decoder = I2C_DRIVERID_SAA7114, + .i2c_decoder = I2C_DRIVERID_SAA711X, .i2c_encoder = I2C_DRIVERID_ADV7170, .video_codec = CODEC_TYPE_ZR36060, @@ -607,7 +604,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 0, "Composite" }, { 7, "S-Video" } }, - .norms = 2, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL, .tvn = { &f50ccir601_lm33r10, &f60ccir601_lm33r10, @@ -625,7 +622,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = BUZ, .name = "Buz", - .i2c_decoder = I2C_DRIVERID_SAA7111A, + .i2c_decoder = I2C_DRIVERID_SAA711X, .i2c_encoder = I2C_DRIVERID_SAA7185B, .video_codec = CODEC_TYPE_ZR36060, @@ -634,7 +631,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 3, "Composite" }, { 7, "S-Video" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50ccir601, &f60ccir601, @@ -671,7 +668,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { {10, "S-Video 3" }, {15, "YCbCr" } }, - .norms = 2, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL, .tvn = { &f50ccir601_avs6eyes, &f60ccir601_avs6eyes, @@ -1087,8 +1084,6 @@ static int __devinit zr36057_init (struct zoran *zr) { int j, err; - int two = 2; - int zero = 0; dprintk(1, KERN_INFO @@ -1114,14 +1109,23 @@ zr36057_init (struct zoran *zr) if (default_norm < VIDEO_MODE_PAL && default_norm > VIDEO_MODE_SECAM) default_norm = VIDEO_MODE_PAL; - zr->norm = default_norm; - if (!(zr->timing = zr->card.tvn[zr->norm])) { + if (default_norm == VIDEO_MODE_PAL) { + zr->norm = V4L2_STD_PAL; + zr->timing = zr->card.tvn[0]; + } else if (default_norm == VIDEO_MODE_NTSC) { + zr->norm = V4L2_STD_NTSC; + zr->timing = zr->card.tvn[1]; + } else { + zr->norm = V4L2_STD_SECAM; + zr->timing = zr->card.tvn[2]; + } + if (zr->timing == NULL) { dprintk(1, KERN_WARNING "%s: zr36057_init() - default TV standard not supported by hardware. PAL will be used.\n", ZR_DEVNAME(zr)); - zr->norm = VIDEO_MODE_PAL; - zr->timing = zr->card.tvn[zr->norm]; + zr->norm = V4L2_STD_PAL; + zr->timing = zr->card.tvn[0]; } if (default_input > zr->card.inputs-1) { @@ -1133,12 +1137,6 @@ zr36057_init (struct zoran *zr) } zr->input = default_input; - /* Should the following be reset at every open ? */ - zr->hue = 32768; - zr->contrast = 32768; - zr->saturation = 32768; - zr->brightness = 32768; - /* default setup (will be repeated at every open) */ zoran_open_init_params(zr); @@ -1174,8 +1172,10 @@ zr36057_init (struct zoran *zr) detect_guest_activity(zr); test_interrupts(zr); if (!pass_through) { - decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero); - encoder_command(zr, ENCODER_SET_INPUT, &two); + struct v4l2_routing route = { 2, 0 }; + + decoder_command(zr, VIDIOC_STREAMOFF, 0); + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); } zr->zoran_proc = NULL; diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index 592300e2f..8544c9b99 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -38,6 +38,8 @@ #include #include "compat.h" #include +#include +#include #include #include @@ -313,9 +315,9 @@ zr36057_adjust_vfe (struct zoran *zr, case BUZ_MODE_MOTION_COMPRESS: case BUZ_MODE_IDLE: default: - if (zr->norm == VIDEO_MODE_NTSC || + if ((zr->norm & V4L2_STD_NTSC) || (zr->card.type == LML33R10 && - zr->norm == VIDEO_MODE_PAL)) + (zr->norm & V4L2_STD_PAL))) btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); else btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); @@ -356,14 +358,6 @@ zr36057_set_vfe (struct zoran *zr, dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n", ZR_DEVNAME(zr), video_width, video_height); - if (zr->norm != VIDEO_MODE_PAL && - zr->norm != VIDEO_MODE_NTSC && - zr->norm != VIDEO_MODE_SECAM) { - dprintk(1, - KERN_ERR "%s: set_vfe() - norm = %d not valid\n", - ZR_DEVNAME(zr), zr->norm); - return; - } if (video_width < BUZ_MIN_WIDTH || video_height < BUZ_MIN_HEIGHT || video_width > Wa || video_height > Ha) { @@ -427,7 +421,7 @@ zr36057_set_vfe (struct zoran *zr, * we get the correct colors when uncompressing to the screen */ //reg |= ZR36057_VFESPFR_VCLKPol; /**/ /* RJ: Don't know if that is needed for NTSC also */ - if (zr->norm != VIDEO_MODE_NTSC) + if (!(zr->norm & V4L2_STD_NTSC)) reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang reg |= ZR36057_VFESPFR_TopField; if (HorDcm >= 48) { @@ -982,11 +976,10 @@ void zr36057_enable_jpg (struct zoran *zr, enum zoran_codec_mode mode) { - static int zero; - static int one = 1; struct vfe_settings cap; int field_size = zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff; + struct v4l2_routing route = { 0, 0 }; zr->codec_mode = mode; @@ -1008,8 +1001,9 @@ zr36057_enable_jpg (struct zoran *zr, * the video bus direction set to input. */ set_videobus_dir(zr, 0); - decoder_command(zr, DECODER_ENABLE_OUTPUT, &one); - encoder_command(zr, ENCODER_SET_INPUT, &zero); + decoder_command(zr, VIDIOC_STREAMON, 0); + route.input = 0; + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1055,9 +1049,10 @@ zr36057_enable_jpg (struct zoran *zr, /* In motion decompression mode, the decoder output must be disabled, and * the video bus direction set to output. */ - decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero); + decoder_command(zr, VIDIOC_STREAMOFF, 0); set_videobus_dir(zr, 1); - encoder_command(zr, ENCODER_SET_INPUT, &one); + route.input = 1; + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1101,8 +1096,9 @@ zr36057_enable_jpg (struct zoran *zr, jpeg_codec_sleep(zr, 1); zr36057_adjust_vfe(zr, mode); - decoder_command(zr, DECODER_ENABLE_OUTPUT, &one); - encoder_command(zr, ENCODER_SET_INPUT, &zero); + decoder_command(zr, VIDIOC_STREAMON, 0); + route.input = 0; + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr)); break; @@ -1212,17 +1208,17 @@ zoran_reap_stat_com (struct zoran *zr) static void zoran_restart(struct zoran *zr) { /* Now the stat_comm buffer is ready for restart */ - int status, mode; + int status = 0, mode; if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - decoder_command(zr, DECODER_GET_STATUS, &status); + decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); mode = CODEC_DO_COMPRESSION; } else { - status = 0; + status = V4L2_IN_ST_NO_SIGNAL; mode = CODEC_DO_EXPANSION; } if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - (status & DECODER_STATUS_GOOD)) { + !(status & V4L2_IN_ST_NO_SIGNAL)) { /********** RESTART code *************/ jpeg_codec_reset(zr); zr->codec->set_mode(zr->codec, mode); @@ -1588,7 +1584,7 @@ zoran_set_pci_master (struct zoran *zr, void zoran_init_hardware (struct zoran *zr) { - int j, zero = 0; + struct v4l2_routing route = { 0, 0 }; /* Enable bus-mastering */ zoran_set_pci_master(zr, 1); @@ -1598,15 +1594,16 @@ zoran_init_hardware (struct zoran *zr) zr->card.init(zr); } - j = zr->card.input[zr->input].muxsel; + route.input = zr->card.input[zr->input].muxsel; - decoder_command(zr, 0, NULL); - decoder_command(zr, DECODER_SET_NORM, &zr->norm); - decoder_command(zr, DECODER_SET_INPUT, &j); + decoder_command(zr, VIDIOC_INT_INIT, NULL); + decoder_command(zr, VIDIOC_S_STD, &zr->norm); + decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); - encoder_command(zr, 0, NULL); - encoder_command(zr, ENCODER_SET_NORM, &zr->norm); - encoder_command(zr, ENCODER_SET_INPUT, &zero); + encoder_command(zr, VIDIOC_INT_INIT, NULL); + encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &zr->norm); + route.input = 0; + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* toggle JPEG codec sleep to sync PLL */ jpeg_codec_sleep(zr, 1); @@ -1680,7 +1677,7 @@ decoder_command (struct zoran *zr, return -EIO; if (zr->card.type == LML33 && - (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) { + (cmd == VIDIOC_S_STD || cmd == VIDIOC_INT_S_VIDEO_ROUTING)) { int res; // Bt819 needs to reset its FIFO buffer using #FRST pin and diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index e67c6caac..5145d2921 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1146,9 +1146,10 @@ zoran_close(struct file *file) zoran_set_pci_master(zr, 0); if (!pass_through) { /* Switch to color bar */ - int zero = 0, two = 2; - decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero); - encoder_command(zr, ENCODER_SET_INPUT, &two); + struct v4l2_routing route = { 2, 0 }; + + decoder_command(zr, VIDIOC_STREAMOFF, 0); + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); } } @@ -1570,9 +1571,9 @@ zoran_v4l2_buffer_status (struct file *file, static int zoran_set_norm (struct zoran *zr, - int norm) /* VIDEO_MODE_* */ + v4l2_std_id norm) { - int norm_encoder, on; + int on; if (zr->v4l_buffers.active != ZORAN_FREE || zr->jpg_buffers.active != ZORAN_FREE) { @@ -1599,52 +1600,42 @@ zoran_set_norm (struct zoran *zr, } } - if (norm != VIDEO_MODE_AUTO && - (norm < 0 || norm >= zr->card.norms || - !zr->card.tvn[norm])) { + if (!(norm & zr->card.norms)) { dprintk(1, - KERN_ERR "%s: set_norm() - unsupported norm %d\n", + KERN_ERR "%s: set_norm() - unsupported norm %llx\n", ZR_DEVNAME(zr), norm); return -EINVAL; } - if (norm == VIDEO_MODE_AUTO) { - int status; + if (norm == V4L2_STD_ALL) { + int status = 0; + v4l2_std_id std = 0; - /* if we have autodetect, ... */ - struct video_decoder_capability caps; - decoder_command(zr, DECODER_GET_CAPABILITIES, &caps); - if (!(caps.flags & VIDEO_DECODER_AUTO)) { - dprintk(1, KERN_ERR "%s: norm=auto unsupported\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - decoder_command(zr, DECODER_SET_NORM, &norm); + decoder_command(zr, VIDIOC_QUERYSTD, &std); + decoder_command(zr, VIDIOC_S_STD, &std); /* let changes come into effect */ ssleep(2); - decoder_command(zr, DECODER_GET_STATUS, &status); - if (!(status & DECODER_STATUS_GOOD)) { + decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); + if (status & V4L2_IN_ST_NO_SIGNAL) { dprintk(1, KERN_ERR "%s: set_norm() - no norm detected\n", ZR_DEVNAME(zr)); /* reset norm */ - decoder_command(zr, DECODER_SET_NORM, &zr->norm); + decoder_command(zr, VIDIOC_S_STD, &zr->norm); return -EIO; } - if (status & DECODER_STATUS_NTSC) - norm = VIDEO_MODE_NTSC; - else if (status & DECODER_STATUS_SECAM) - norm = VIDEO_MODE_SECAM; - else - norm = VIDEO_MODE_PAL; + norm = std; } - zr->timing = zr->card.tvn[norm]; - norm_encoder = norm; + if (norm & V4L2_STD_SECAM) + zr->timing = zr->card.tvn[2]; + else if (norm & V4L2_STD_NTSC) + zr->timing = zr->card.tvn[1]; + else + zr->timing = zr->card.tvn[0]; /* We switch overlay off and on since a change in the * norm needs different VFE settings */ @@ -1652,8 +1643,8 @@ zoran_set_norm (struct zoran *zr, if (on) zr36057_overlay(zr, 0); - decoder_command(zr, DECODER_SET_NORM, &norm); - encoder_command(zr, ENCODER_SET_NORM, &norm_encoder); + decoder_command(zr, VIDIOC_S_STD, &norm); + encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &norm); if (on) zr36057_overlay(zr, 1); @@ -1668,7 +1659,7 @@ static int zoran_set_input (struct zoran *zr, int input) { - int realinput; + struct v4l2_routing route = { 0, 0 }; if (input == zr->input) { return 0; @@ -1691,10 +1682,10 @@ zoran_set_input (struct zoran *zr, return -EINVAL; } - realinput = zr->card.input[input].muxsel; + route.input = zr->card.input[input].muxsel; zr->input = input; - decoder_command(zr, DECODER_SET_INPUT, &realinput); + decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); return 0; } @@ -1723,7 +1714,13 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) mutex_lock(&zr->resource_lock); - bparams->norm = zr->norm; + if (zr->norm & V4L2_STD_NTSC) + bparams->norm = VIDEO_MODE_NTSC; + else if (zr->norm & V4L2_STD_PAL) + bparams->norm = VIDEO_MODE_PAL; + else + bparams->norm = VIDEO_MODE_SECAM; + bparams->input = zr->input; bparams->decimation = fh->jpg_settings.decimation; @@ -1906,7 +1903,9 @@ jpgreqbuf_unlock_and_return: case BUZIOC_G_STATUS: { struct zoran_status *bstat = arg; - int norm, input, status, res = 0; + struct v4l2_routing route = { 0, 0 }; + int status = 0, res = 0; + v4l2_std_id norm; dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr)); @@ -1918,8 +1917,7 @@ jpgreqbuf_unlock_and_return: return -EINVAL; } - input = zr->card.input[bstat->input].muxsel; - norm = VIDEO_MODE_AUTO; + route.input = zr->card.input[bstat->input].muxsel; mutex_lock(&zr->resource_lock); @@ -1932,34 +1930,33 @@ jpgreqbuf_unlock_and_return: goto gstat_unlock_and_return; } - decoder_command(zr, DECODER_SET_INPUT, &input); - decoder_command(zr, DECODER_SET_NORM, &norm); + decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* sleep 1 second */ ssleep(1); /* Get status of video decoder */ - decoder_command(zr, DECODER_GET_STATUS, &status); + decoder_command(zr, VIDIOC_QUERYSTD, &norm); + decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); /* restore previous input and norm */ - input = zr->card.input[zr->input].muxsel; - decoder_command(zr, DECODER_SET_INPUT, &input); - decoder_command(zr, DECODER_SET_NORM, &zr->norm); + route.input = zr->card.input[zr->input].muxsel; + decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); if (!res) { bstat->signal = - (status & DECODER_STATUS_GOOD) ? 1 : 0; - if (status & DECODER_STATUS_NTSC) + (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1; + if (norm & V4L2_STD_NTSC) bstat->norm = VIDEO_MODE_NTSC; - else if (status & DECODER_STATUS_SECAM) + else if (norm & V4L2_STD_SECAM) bstat->norm = VIDEO_MODE_SECAM; else bstat->norm = VIDEO_MODE_PAL; bstat->color = - (status & DECODER_STATUS_COLOR) ? 1 : 0; + (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1; } return res; @@ -2868,37 +2865,15 @@ strmoff_unlock_and_return: static int zoran_queryctrl(struct file *file, void *__fh, struct v4l2_queryctrl *ctrl) { + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + /* we only support hue/saturation/contrast/brightness */ if (ctrl->id < V4L2_CID_BRIGHTNESS || ctrl->id > V4L2_CID_HUE) return -EINVAL; - else { - int id = ctrl->id; - memset(ctrl, 0, sizeof(*ctrl)); - ctrl->id = id; - } - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1); - break; - case V4L2_CID_CONTRAST: - strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1); - break; - case V4L2_CID_SATURATION: - strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1); - break; - case V4L2_CID_HUE: - strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1); - break; - } - ctrl->minimum = 0; - ctrl->maximum = 65535; - ctrl->step = 1; - ctrl->default_value = 32768; - ctrl->type = V4L2_CTRL_TYPE_INTEGER; - ctrl->flags = V4L2_CTRL_FLAG_SLIDER; + decoder_command(zr, VIDIOC_QUERYCTRL, ctrl); return 0; } @@ -2914,20 +2889,7 @@ static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl return -EINVAL; mutex_lock(&zr->resource_lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = zr->brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = zr->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = zr->saturation; - break; - case V4L2_CID_HUE: - ctrl->value = zr->hue; - break; - } + decoder_command(zr, VIDIOC_G_CTRL, ctrl); mutex_unlock(&zr->resource_lock); return 0; @@ -2937,42 +2899,14 @@ static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - struct video_picture pict; /* we only support hue/saturation/contrast/brightness */ if (ctrl->id < V4L2_CID_BRIGHTNESS || ctrl->id > V4L2_CID_HUE) return -EINVAL; - if (ctrl->value < 0 || ctrl->value > 65535) { - dprintk(1, KERN_ERR - "%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n", - ZR_DEVNAME(zr), ctrl->value, ctrl->id); - return -EINVAL; - } - mutex_lock(&zr->resource_lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - zr->brightness = ctrl->value; - break; - case V4L2_CID_CONTRAST: - zr->contrast = ctrl->value; - break; - case V4L2_CID_SATURATION: - zr->saturation = ctrl->value; - break; - case V4L2_CID_HUE: - zr->hue = ctrl->value; - break; - } - pict.brightness = zr->brightness; - pict.contrast = zr->contrast; - pict.colour = zr->saturation; - pict.hue = zr->hue; - - decoder_command(zr, DECODER_SET_PICTURE, &pict); - + decoder_command(zr, VIDIOC_S_CTRL, ctrl); mutex_unlock(&zr->resource_lock); return 0; @@ -2982,24 +2916,10 @@ static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std) { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - int norm; mutex_lock(&zr->resource_lock); - norm = zr->norm; + *std = zr->norm; mutex_unlock(&zr->resource_lock); - - switch (norm) { - case VIDEO_MODE_PAL: - *std = V4L2_STD_PAL; - break; - case VIDEO_MODE_NTSC: - *std = V4L2_STD_NTSC; - break; - case VIDEO_MODE_SECAM: - *std = V4L2_STD_SECAM; - break; - } - return 0; } @@ -3007,25 +2927,10 @@ static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std) { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - int norm = -1, res = 0; - - if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL)) - norm = VIDEO_MODE_PAL; - else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC)) - norm = VIDEO_MODE_NTSC; - else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM)) - norm = VIDEO_MODE_SECAM; - else if (*std == V4L2_STD_ALL) - norm = VIDEO_MODE_AUTO; - else { - dprintk(1, KERN_ERR - "%s: VIDIOC_S_STD - invalid norm 0x%llx\n", - ZR_DEVNAME(zr), (unsigned long long)*std); - return -EINVAL; - } + int res = 0; mutex_lock(&zr->resource_lock); - res = zoran_set_norm(zr, norm); + res = zoran_set_norm(zr, *std); if (res) goto sstd_unlock_and_return; @@ -3040,7 +2945,6 @@ static int zoran_enum_input(struct file *file, void *__fh, { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - int status; if (inp->index < 0 || inp->index >= zr->card.inputs) return -EINVAL; @@ -3057,16 +2961,8 @@ static int zoran_enum_input(struct file *file, void *__fh, /* Get status of video decoder */ mutex_lock(&zr->resource_lock); - decoder_command(zr, DECODER_GET_STATUS, &status); + decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &inp->status); mutex_unlock(&zr->resource_lock); - - if (!(status & DECODER_STATUS_GOOD)) { - inp->status |= V4L2_IN_ST_NO_POWER; - inp->status |= V4L2_IN_ST_NO_SIGNAL; - } - if (!(status & DECODER_STATUS_COLOR)) - inp->status |= V4L2_IN_ST_NO_COLOR; - return 0; } -- cgit v1.2.3 From 5ac82a7507d0e50ce9a90a524c6d2d410c1de604 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 21:39:45 +0100 Subject: zoran: clean up some old V4L1 left-overs and remove the MAP_NR macro. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran.h | 3 - linux/drivers/media/video/zoran/zoran_driver.c | 130 ++++++++----------------- 2 files changed, 43 insertions(+), 90 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran.h b/linux/drivers/media/video/zoran/zoran.h index ee31bfc34..a323eb66e 100644 --- a/linux/drivers/media/video/zoran/zoran.h +++ b/linux/drivers/media/video/zoran/zoran.h @@ -238,9 +238,6 @@ enum gpcs_type { struct zoran_format { char *name; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - int palette; -#endif __u32 fourcc; int colorspace; int depth; diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 5145d2921..96085b123 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -58,16 +58,6 @@ #include #include -#define MAP_NR(x) virt_to_page(x) -#define ZORAN_VID_TYPE ( \ - VID_TYPE_CAPTURE | \ - VID_TYPE_OVERLAY | \ - VID_TYPE_CLIPPING | \ - VID_TYPE_FRAMERAM | \ - VID_TYPE_SCALES | \ - VID_TYPE_MJPEG_DECODER | \ - VID_TYPE_MJPEG_ENCODER \ - ) #include #include @@ -87,29 +77,12 @@ #include "zoran_device.h" #include "zoran_card.h" - /* we declare some card type definitions here, they mean - * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */ -#define ZORAN_V4L2_VID_FLAGS ( \ - V4L2_CAP_STREAMING |\ - V4L2_CAP_VIDEO_CAPTURE |\ - V4L2_CAP_VIDEO_OUTPUT |\ - V4L2_CAP_VIDEO_OVERLAY \ - ) - - -#if defined(CONFIG_VIDEO_V4L1_COMPAT) -#define ZFMT(pal, fcc, cs) \ - .palette = (pal), .fourcc = (fcc), .colorspace = (cs) -#else -#define ZFMT(pal, fcc, cs) \ - .fourcc = (fcc), .colorspace = (cs) -#endif const struct zoran_format zoran_formats[] = { { .name = "15-bit RGB LE", - ZFMT(VIDEO_PALETTE_RGB555, - V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB555, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 15, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, @@ -117,16 +90,16 @@ const struct zoran_format zoran_formats[] = { ZR36057_VFESPFR_LittleEndian, }, { .name = "15-bit RGB BE", - ZFMT(-1, - V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB555X, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 15, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif, }, { .name = "16-bit RGB LE", - ZFMT(VIDEO_PALETTE_RGB565, - V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB565, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, @@ -134,56 +107,56 @@ const struct zoran_format zoran_formats[] = { ZR36057_VFESPFR_LittleEndian, }, { .name = "16-bit RGB BE", - ZFMT(-1, - V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB565X, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif, }, { .name = "24-bit RGB", - ZFMT(VIDEO_PALETTE_RGB24, - V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_BGR24, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 24, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24, }, { .name = "32-bit RGB LE", - ZFMT(VIDEO_PALETTE_RGB32, - V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_BGR32, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 32, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian, }, { .name = "32-bit RGB BE", - ZFMT(-1, - V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB32, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 32, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB888, }, { .name = "4:2:2, packed, YUYV", - ZFMT(VIDEO_PALETTE_YUV422, - V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M), + .fourcc = V4L2_PIX_FMT_YUYV, + .colorspace = V4L2_COLORSPACE_SMPTE170M, .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_YUV422, }, { .name = "4:2:2, packed, UYVY", - ZFMT(VIDEO_PALETTE_UYVY, - V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M), + .fourcc = V4L2_PIX_FMT_UYVY, + .colorspace = V4L2_COLORSPACE_SMPTE170M, .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian, }, { .name = "Hardware-encoded Motion-JPEG", - ZFMT(-1, - V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M), + .fourcc = V4L2_PIX_FMT_MJPEG, + .colorspace = V4L2_COLORSPACE_SMPTE170M, .depth = 0, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_PLAYBACK | @@ -261,7 +234,7 @@ v4l_fbuffer_alloc (struct file *file) virt_to_bus(mem); for (off = 0; off < fh->v4l_buffers.buffer_size; off += PAGE_SIZE) - SetPageReserved(MAP_NR(mem + off)); + SetPageReserved(virt_to_page(mem + off)); dprintk(4, KERN_INFO "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", @@ -292,7 +265,7 @@ v4l_fbuffer_free (struct file *file) mem = fh->v4l_buffers.buffer[i].fbuffer; for (off = 0; off < fh->v4l_buffers.buffer_size; off += PAGE_SIZE) - ClearPageReserved(MAP_NR(mem + off)); + ClearPageReserved(virt_to_page(mem + off)); kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); fh->v4l_buffers.buffer[i].fbuffer = NULL; } @@ -378,7 +351,7 @@ jpg_fbuffer_alloc (struct file *file) cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1); for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE) - SetPageReserved(MAP_NR(mem + off)); + SetPageReserved(virt_to_page(mem + off)); } else { /* jpg_bufsize is already page aligned */ for (j = 0; @@ -399,7 +372,7 @@ jpg_fbuffer_alloc (struct file *file) fh->jpg_buffers.buffer[i].frag_tab[2 * j + 1] = cpu_to_le32((PAGE_SIZE / 4) << 1); - SetPageReserved(MAP_NR(mem)); + SetPageReserved(virt_to_page(mem)); } fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1); @@ -425,6 +398,7 @@ jpg_fbuffer_free (struct file *file) struct zoran *zr = fh->zr; int i, j, off; unsigned char *mem; + __le32 frag_tab; dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr)); @@ -432,48 +406,31 @@ jpg_fbuffer_free (struct file *file) if (!fh->jpg_buffers.buffer[i].frag_tab) continue; - //if (alloc_contig) { if (fh->jpg_buffers.need_contiguous) { - if (fh->jpg_buffers.buffer[i].frag_tab[0]) { - mem = (unsigned char *) bus_to_virt(le32_to_cpu( - fh->jpg_buffers.buffer[i].frag_tab[0])); - for (off = 0; - off < fh->jpg_buffers.buffer_size; - off += PAGE_SIZE) - ClearPageReserved(MAP_NR - (mem + off)); + frag_tab = fh->jpg_buffers.buffer[i].frag_tab[0]; + + if (frag_tab) { + mem = (unsigned char *)bus_to_virt(le32_to_cpu(frag_tab)); + for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE) + ClearPageReserved(virt_to_page(mem + off)); kfree(mem); fh->jpg_buffers.buffer[i].frag_tab[0] = 0; fh->jpg_buffers.buffer[i].frag_tab[1] = 0; } } else { - for (j = 0; - j < fh->jpg_buffers.buffer_size / PAGE_SIZE; - j++) { - if (!fh->jpg_buffers.buffer[i]. - frag_tab[2 * j]) + for (j = 0; j < fh->jpg_buffers.buffer_size / PAGE_SIZE; j++) { + frag_tab = fh->jpg_buffers.buffer[i].frag_tab[2 * j]; + + if (!frag_tab) break; - ClearPageReserved(MAP_NR - (bus_to_virt - (le32_to_cpu - (fh->jpg_buffers. - buffer[i].frag_tab[2 * - j])))); - free_page((unsigned long) - bus_to_virt - (le32_to_cpu - (fh->jpg_buffers. - buffer[i]. - frag_tab[2 * j]))); - fh->jpg_buffers.buffer[i].frag_tab[2 * j] = - 0; - fh->jpg_buffers.buffer[i].frag_tab[2 * j + - 1] = 0; + ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab)))); + free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab))); + fh->jpg_buffers.buffer[i].frag_tab[2 * j] = 0; + fh->jpg_buffers.buffer[i].frag_tab[2 * j + 1] = 0; } } - free_page((unsigned long) fh->jpg_buffers.buffer[i]. - frag_tab); + free_page((unsigned long)fh->jpg_buffers.buffer[i].frag_tab); fh->jpg_buffers.buffer[i].frag_tab = NULL; } @@ -2017,11 +1974,10 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability strncpy(cap->driver, "zoran", sizeof(cap->driver)-1); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(zr->pci_dev)); - cap->version = - KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION, + cap->version = KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION); - cap->capabilities = ZORAN_V4L2_VID_FLAGS; - + cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY; return 0; } -- cgit v1.2.3 From a9e2b393853fab732f68350caf74d3f8057ed8f1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 22:33:35 +0100 Subject: zoran: change buffer defaults to something that works with tvtime From: Hans Verkuil By popular request increased the default number and size of the buffers to something that tvtime likes. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_card.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 17c3aaffd..37f75045f 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -126,8 +126,8 @@ MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); */ -int v4l_nbufs = 2; -int v4l_bufsize = 128; /* Everybody should be able to work with this setting */ +int v4l_nbufs = 4; +int v4l_bufsize = 810; /* Everybody should be able to work with this setting */ module_param(v4l_nbufs, int, 0644); MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use"); module_param(v4l_bufsize, int, 0644); -- cgit v1.2.3 From bb9189ca522bccdf0c7d76b92a5860b074bc0c02 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 22:34:55 +0100 Subject: zoran: TRY_FMT and S_FMT now do the same parameter checks. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 96085b123..66659d479 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2132,8 +2132,6 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) return -EINVAL; - fmt->fmt.pix.bytesperline = 0; - mutex_lock(&zr->resource_lock); settings = fh->jpg_settings; @@ -2158,6 +2156,14 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, else settings.field_per_buff = 1; + if (settings.HorDcm > 1) { + settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0; + settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH; + } else { + settings.img_x = 0; + settings.img_width = BUZ_MAX_WIDTH; + } + /* check */ res = zoran_check_jpg_settings(zr, &settings, 1); if (res) @@ -2175,6 +2181,8 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings); + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; tryfmt_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; -- cgit v1.2.3 From 353efa42bb001bd99872fdedd37a76d4fc085b23 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 08:49:29 +0100 Subject: bt866: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt866.c | 231 ++++++++++++++++++++------------------ 1 file changed, 122 insertions(+), 109 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index 5aed3c7f1..9f53b8176 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -34,9 +34,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include "compat.h" @@ -48,21 +48,25 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ struct bt866 { + struct v4l2_subdev sd; u8 reg[256]; - - v4l2_std_id norm; - int bright; - int contrast; - int hue; - int sat; }; -static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data) +static inline struct bt866 *to_bt866(struct v4l2_subdev *sd) { - struct bt866 *encoder = i2c_get_clientdata(client); + return container_of(sd, struct bt866, sd); +} + +static int bt866_write(struct bt866 *encoder, u8 subaddr, u8 data) +{ + struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd); u8 buffer[2]; int err; @@ -89,119 +93,125 @@ static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data) return 0; } -static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) +static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - struct bt866 *encoder = i2c_get_clientdata(client); + v4l2_dbg(1, debug, sd, "set norm %llx\n", std); - switch (cmd) { - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id *iarg = arg; - - v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); + /* Only PAL supported by this driver at the moment! */ + if (!(std & V4L2_STD_NTSC)) + return -EINVAL; + return 0; +} - if (!(*iarg & (V4L2_STD_NTSC | V4L2_STD_PAL))) - return -EINVAL; - encoder->norm = *iarg; +static int bt866_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + static const __u8 init[] = { + 0xc8, 0xcc, /* CRSCALE */ + 0xca, 0x91, /* CBSCALE */ + 0xcc, 0x24, /* YC16 | OSDNUM */ + 0xda, 0x00, /* */ + 0xdc, 0x24, /* SETMODE | PAL */ + 0xde, 0x02, /* EACTIVE */ + + /* overlay colors */ + 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */ + 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */ + 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */ + 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */ + 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */ + 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */ + 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */ + 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */ + + 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */ + 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */ + 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */ + 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */ + 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */ + 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */ + 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */ + 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */ + }; + struct bt866 *encoder = to_bt866(sd); + u8 val; + int i; + + for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) + bt866_write(encoder, init[i], init[i+1]); + + val = encoder->reg[0xdc]; + + if (route->input == 0) + val |= 0x40; /* CBSWAP */ + else + val &= ~0x40; /* !CBSWAP */ + + bt866_write(encoder, 0xdc, val); + + val = encoder->reg[0xcc]; + if (route->input == 2) + val |= 0x01; /* OSDBAR */ + else + val &= ~0x01; /* !OSDBAR */ + bt866_write(encoder, 0xcc, val); + + v4l2_dbg(1, debug, sd, "set input %d\n", route->input); + + switch (route->input) { + case 0: + case 1: + case 2: break; + default: + return -EINVAL; } + return 0; +} - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - static const __u8 init[] = { - 0xc8, 0xcc, /* CRSCALE */ - 0xca, 0x91, /* CBSCALE */ - 0xcc, 0x24, /* YC16 | OSDNUM */ - 0xda, 0x00, /* */ - 0xdc, 0x24, /* SETMODE | PAL */ - 0xde, 0x02, /* EACTIVE */ - - /* overlay colors */ - 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */ - 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */ - 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */ - 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */ - 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */ - 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */ - 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */ - 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */ - - 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */ - 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */ - 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */ - 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */ - 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */ - 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */ - 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */ - 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */ - }; - int i; - u8 val; - - for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) - bt866_write(client, init[i], init[i+1]); - - val = encoder->reg[0xdc]; - - if (route->input == 0) - val |= 0x40; /* CBSWAP */ - else - val &= ~0x40; /* !CBSWAP */ - - bt866_write(client, 0xdc, val); - - val = encoder->reg[0xcc]; - if (route->input == 2) - val |= 0x01; /* OSDBAR */ - else - val &= ~0x01; /* !OSDBAR */ - bt866_write(client, 0xcc, val); - - v4l_dbg(1, debug, client, "set input %d\n", route->input); - - switch (route->input) { - case 0: - break; - case 1: - break; - default: - return -EINVAL; - } - break; - } +#if 0 /* keep */ +/* Code to setup square pixels, might be of some use in the future, + but is currently unused. */ + val = encoder->reg[0xdc]; + if (*iarg) + val |= 1; /* SQUARE */ + else + val &= ~1; /* !SQUARE */ + bt866_write(client, 0xdc, val); +#endif - case 4711: - { - int *iarg = arg; - __u8 val; +static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - v4l_dbg(1, debug, client, "square %d\n", *iarg); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); +} - val = encoder->reg[0xdc]; - if (*iarg) - val |= 1; /* SQUARE */ - else - val &= ~1; /* !SQUARE */ - bt866_write(client, 0xdc, val); - break; - } +static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} - default: - return -EINVAL; - } +/* ----------------------------------------------------------------------- */ - return 0; -} +static const struct v4l2_subdev_core_ops bt866_core_ops = { + .g_chip_ident = bt866_g_chip_ident, +}; -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_video_ops bt866_video_ops = { + .s_std_output = bt866_s_std_output, + .s_routing = bt866_s_routing, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_ops bt866_ops = { + .core = &bt866_core_ops, + .video = &bt866_video_ops, +}; static int bt866_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct bt866 *encoder; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -209,14 +219,17 @@ static int bt866_probe(struct i2c_client *client, encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - - i2c_set_clientdata(client, encoder); + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &bt866_ops); return 0; } static int bt866_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_bt866(sd)); return 0; } -- cgit v1.2.3 From fbef599baf91dd9e8d3926f440a4087b8eaaaeb1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:11:25 +0100 Subject: soc-camera: fix S_CROP breakage on PXA and SuperH From: Guennadi Liakhovetski Recent format-negotiation patches caused S_CROP breakage in pxa_camera.c and sh_mobile_ceu_camera.c drivers, fix it. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 26 +++++++++++++------------- drivers/media/video/sh_mobile_ceu_camera.c | 13 +++++-------- 2 files changed, 18 insertions(+), 21 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 26 ++++++++++++------------ linux/drivers/media/video/sh_mobile_ceu_camera.c | 13 +++++------- 2 files changed, 18 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 2c283b82a..b6a34ba18 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1164,23 +1164,23 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL; - const struct soc_camera_format_xlate *xlate; + const struct soc_camera_data_format *cam_fmt = NULL; + const struct soc_camera_format_xlate *xlate = NULL; struct soc_camera_sense sense = { .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, }; - int ret, buswidth; + int ret; - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); - return -EINVAL; - } + if (pixfmt) { + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } - buswidth = xlate->buswidth; - host_fmt = xlate->host_fmt; - cam_fmt = xlate->cam_fmt; + cam_fmt = xlate->cam_fmt; + } /* If PCLK is used to latch data from the sensor, check sense */ if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) @@ -1210,8 +1210,8 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, } if (pixfmt && !ret) { - icd->buswidth = buswidth; - icd->current_fmt = host_fmt; + icd->buswidth = xlate->buswidth; + icd->current_fmt = xlate->host_fmt; } return ret; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index ae98eaf5f..ee113de47 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -604,21 +604,18 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, const struct soc_camera_format_xlate *xlate; int ret; + if (!pixfmt) + return icd->ops->set_fmt(icd, pixfmt, rect); + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { dev_warn(&ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } - switch (pixfmt) { - case 0: /* Only geometry change */ - ret = icd->ops->set_fmt(icd, pixfmt, rect); - break; - default: - ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); - } + ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); - if (pixfmt && !ret) { + if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; pcdev->camera_fmt = xlate->cam_fmt; -- cgit v1.2.3 From f694b3bdfb8fc63dc886d6feded8574e91562eb7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 10:36:36 +0100 Subject: bt819: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt819.c | 477 ++++++++++++++++++++------------------ 1 file changed, 252 insertions(+), 225 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index cd85ea462..5c1ab1c74 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -29,15 +29,14 @@ */ #include -#include #include #include #include #include #include -#include -#include -#include +#include +#include +#include #include #include "compat.h" @@ -49,13 +48,18 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ struct bt819 { + struct v4l2_subdev sd; unsigned char reg[32]; - int initialized; v4l2_std_id norm; + int ident; int input; int enable; int bright; @@ -64,6 +68,11 @@ struct bt819 { int sat; }; +static inline struct bt819 *to_bt819(struct v4l2_subdev *sd) +{ + return container_of(sd, struct bt819, sd); +} + struct timing { int hactive; int hdelay; @@ -81,24 +90,23 @@ static struct timing timing_data[] = { /* ----------------------------------------------------------------------- */ -static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value) +static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value) { - struct bt819 *decoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd); decoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) +static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value) { - struct bt819 *decoder = i2c_get_clientdata(client); - - return bt819_write(client, reg, + return bt819_write(decoder, reg, (decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0)); } -static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len) +static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd); int ret = -1; u8 reg; @@ -106,7 +114,6 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct bt819 *decoder = i2c_get_clientdata(client); u8 block_data[32]; int block_len; @@ -127,7 +134,8 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - if ((ret = bt819_write(client, reg, *data++)) < 0) + ret = bt819_write(decoder, reg, *data++); + if (ret < 0) break; len -= 2; } @@ -136,15 +144,15 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned return ret; } -static inline int bt819_read(struct i2c_client *client, u8 reg) +static inline int bt819_read(struct bt819 *decoder, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd); + return i2c_smbus_read_byte_data(client, reg); } -static int bt819_init(struct i2c_client *client) +static int bt819_init(struct v4l2_subdev *sd) { - struct bt819 *decoder = i2c_get_clientdata(client); - static unsigned char init[] = { /*0x1f, 0x00,*/ /* Reset */ 0x01, 0x59, /* 0x01 input format */ @@ -179,6 +187,7 @@ static int bt819_init(struct i2c_client *client) 0x1a, 0x80, /* 0x1a ADC Interface */ }; + struct bt819 *decoder = to_bt819(sd); struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0]; init[0x03 * 2 - 1] = @@ -195,277 +204,297 @@ static int bt819_init(struct i2c_client *client) /* 0x15 in array is address 0x19 */ init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93; /* Chroma burst delay */ /* reset */ - bt819_write(client, 0x1f, 0x00); + bt819_write(decoder, 0x1f, 0x00); mdelay(1); /* init */ - return bt819_write_block(client, init, sizeof(init)); + return bt819_write_block(decoder, init, sizeof(init)); } /* ----------------------------------------------------------------------- */ -static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) +static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) { - int temp; + struct bt819 *decoder = to_bt819(sd); + int status = bt819_read(decoder, 0x00); + int res = V4L2_IN_ST_NO_SIGNAL; + v4l2_std_id std; + + if ((status & 0x80)) + res = 0; + + if ((status & 0x10)) + std = V4L2_STD_PAL; + else + std = V4L2_STD_NTSC; + if (pstd) + *pstd = std; + if (pstatus) + *pstatus = status; + + v4l2_dbg(1, debug, sd, "get status %x\n", status); + return 0; +} - struct bt819 *decoder = i2c_get_clientdata(client); +static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + return bt819_status(sd, NULL, std); +} - if (!decoder->initialized) { /* First call to bt819_init could be */ - bt819_init(client); /* without #FRST = 0 */ - decoder->initialized = 1; +static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + return bt819_status(sd, status, NULL); +} + +static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct bt819 *decoder = to_bt819(sd); + struct timing *timing = NULL; + + v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + + if (std & V4L2_STD_NTSC) { + bt819_setbit(decoder, 0x01, 0, 1); + bt819_setbit(decoder, 0x01, 1, 0); + bt819_setbit(decoder, 0x01, 5, 0); + bt819_write(decoder, 0x18, 0x68); + bt819_write(decoder, 0x19, 0x5d); + /* bt819_setbit(decoder, 0x1a, 5, 1); */ + timing = &timing_data[1]; + } else if (std & V4L2_STD_PAL) { + bt819_setbit(decoder, 0x01, 0, 1); + bt819_setbit(decoder, 0x01, 1, 1); + bt819_setbit(decoder, 0x01, 5, 1); + bt819_write(decoder, 0x18, 0x7f); + bt819_write(decoder, 0x19, 0x72); + /* bt819_setbit(decoder, 0x1a, 5, 0); */ + timing = &timing_data[0]; + } else { + v4l2_dbg(1, debug, sd, "unsupported norm %llx\n", std); + return -EINVAL; } + bt819_write(decoder, 0x03, + (((timing->vdelay >> 8) & 0x03) << 6) | + (((timing->vactive >> 8) & 0x03) << 4) | + (((timing->hdelay >> 8) & 0x03) << 2) | + ((timing->hactive >> 8) & 0x03)); + bt819_write(decoder, 0x04, timing->vdelay & 0xff); + bt819_write(decoder, 0x05, timing->vactive & 0xff); + bt819_write(decoder, 0x06, timing->hdelay & 0xff); + bt819_write(decoder, 0x07, timing->hactive & 0xff); + bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); + bt819_write(decoder, 0x09, timing->hscale & 0xff); + decoder->norm = std; + return 0; +} - switch (cmd) { - case VIDIOC_INT_INIT: - /* This is just for testing!!! */ - bt819_init(client); - break; +static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct bt819 *decoder = to_bt819(sd); - case VIDIOC_QUERYSTD: - case VIDIOC_INT_G_INPUT_STATUS: { - int *iarg = arg; - v4l2_std_id *istd = arg; - int status; - int res = V4L2_IN_ST_NO_SIGNAL; - v4l2_std_id std; - - status = bt819_read(client, 0x00); - if ((status & 0x80)) - res = 0; - - if ((status & 0x10)) - std = V4L2_STD_PAL; - else - std = V4L2_STD_NTSC; - if (cmd == VIDIOC_QUERYSTD) - *istd = std; - else - *iarg = res; - - v4l_dbg(1, debug, client, "get status %x\n", *iarg); - break; - } + v4l2_dbg(1, debug, sd, "set input %x\n", route->input); - case VIDIOC_S_STD: - { - v4l2_std_id *iarg = arg; - struct timing *timing = NULL; - - v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - - if (*iarg & V4L2_STD_NTSC) { - bt819_setbit(client, 0x01, 0, 1); - bt819_setbit(client, 0x01, 1, 0); - bt819_setbit(client, 0x01, 5, 0); - bt819_write(client, 0x18, 0x68); - bt819_write(client, 0x19, 0x5d); - /* bt819_setbit(client, 0x1a, 5, 1); */ - timing = &timing_data[1]; - } else if (*iarg & V4L2_STD_PAL) { - bt819_setbit(client, 0x01, 0, 1); - bt819_setbit(client, 0x01, 1, 1); - bt819_setbit(client, 0x01, 5, 1); - bt819_write(client, 0x18, 0x7f); - bt819_write(client, 0x19, 0x72); - /* bt819_setbit(client, 0x1a, 5, 0); */ - timing = &timing_data[0]; - } else { - v4l_dbg(1, debug, client, "unsupported norm %llx\n", *iarg); - return -EINVAL; - } -/* case VIDEO_MODE_AUTO: - bt819_setbit(client, 0x01, 0, 0); - bt819_setbit(client, 0x01, 1, 0);*/ - - bt819_write(client, 0x03, - (((timing->vdelay >> 8) & 0x03) << 6) | - (((timing->vactive >> 8) & 0x03) << 4) | - (((timing->hdelay >> 8) & 0x03) << 2) | - ((timing->hactive >> 8) & 0x03)); - bt819_write(client, 0x04, timing->vdelay & 0xff); - bt819_write(client, 0x05, timing->vactive & 0xff); - bt819_write(client, 0x06, timing->hdelay & 0xff); - bt819_write(client, 0x07, timing->hactive & 0xff); - bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff); - bt819_write(client, 0x09, timing->hscale & 0xff); - decoder->norm = *iarg; - break; - } + if (route->input < 0 || route->input > 7) + return -EINVAL; - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - v4l_dbg(1, debug, client, "set input %x\n", route->input); - - if (route->input < 0 || route->input > 7) - return -EINVAL; - - if (decoder->input != route->input) { - decoder->input = route->input; - /* select mode */ - if (decoder->input == 0) { - bt819_setbit(client, 0x0b, 6, 0); - bt819_setbit(client, 0x1a, 1, 1); - } else { - bt819_setbit(client, 0x0b, 6, 1); - bt819_setbit(client, 0x1a, 1, 0); - } + if (decoder->input != route->input) { + decoder->input = route->input; + /* select mode */ + if (decoder->input == 0) { + bt819_setbit(decoder, 0x0b, 6, 0); + bt819_setbit(decoder, 0x1a, 1, 1); + } else { + bt819_setbit(decoder, 0x0b, 6, 1); + bt819_setbit(decoder, 0x1a, 1, 0); } - break; } + return 0; +} - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - { - int enable = cmd == VIDIOC_STREAMON; +static int bt819_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct bt819 *decoder = to_bt819(sd); - v4l_dbg(1, debug, client, "enable output %x\n", enable); + v4l2_dbg(1, debug, sd, "enable output %x\n", enable); - if (decoder->enable != enable) { - decoder->enable = enable; - bt819_setbit(client, 0x16, 7, !enable); - } - break; + if (decoder->enable != enable) { + decoder->enable = enable; + bt819_setbit(decoder, 0x16, 7, !enable); } + return 0; +} - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); - break; - - case V4L2_CID_CONTRAST: - v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); - break; +static int bt819_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; - case V4L2_CID_SATURATION: - v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); - break; + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); + break; - case V4L2_CID_HUE: - v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); - break; + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); + break; - default: - return -EINVAL; - } + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); break; + + default: + return -EINVAL; } + return 0; +} - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; +static int bt819_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct bt819 *decoder = to_bt819(sd); + int temp; - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if (decoder->bright != ctrl->value) { - decoder->bright = ctrl->value; - bt819_write(client, 0x0a, decoder->bright); - } + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright == ctrl->value) break; + decoder->bright = ctrl->value; + bt819_write(decoder, 0x0a, decoder->bright); + break; - case V4L2_CID_CONTRAST: - if (decoder->contrast != ctrl->value) { - decoder->contrast = ctrl->value; - bt819_write(client, 0x0c, - decoder->contrast & 0xff); - bt819_setbit(client, 0x0b, 2, - ((decoder->contrast >> 8) & 0x01)); - } + case V4L2_CID_CONTRAST: + if (decoder->contrast == ctrl->value) break; + decoder->contrast = ctrl->value; + bt819_write(decoder, 0x0c, decoder->contrast & 0xff); + bt819_setbit(decoder, 0x0b, 2, ((decoder->contrast >> 8) & 0x01)); + break; - case V4L2_CID_SATURATION: - if (decoder->sat != ctrl->value) { - decoder->sat = ctrl->value; - bt819_write(client, 0x0d, - (decoder->sat >> 7) & 0xff); - bt819_setbit(client, 0x0b, 1, - ((decoder->sat >> 15) & 0x01)); - - /* Ratio between U gain and V gain must stay the same as - the ratio between the default U and V gain values. */ - temp = (decoder->sat * 180) / 254; - bt819_write(client, 0x0e, (temp >> 7) & 0xff); - bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01); - } + case V4L2_CID_SATURATION: + if (decoder->sat == ctrl->value) break; + decoder->sat = ctrl->value; + bt819_write(decoder, 0x0d, (decoder->sat >> 7) & 0xff); + bt819_setbit(decoder, 0x0b, 1, ((decoder->sat >> 15) & 0x01)); + + /* Ratio between U gain and V gain must stay the same as + the ratio between the default U and V gain values. */ + temp = (decoder->sat * 180) / 254; + bt819_write(decoder, 0x0e, (temp >> 7) & 0xff); + bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01); + break; - case V4L2_CID_HUE: - if (decoder->hue != ctrl->value) { - decoder->hue = ctrl->value; - bt819_write(client, 0x0f, decoder->hue); - } + case V4L2_CID_HUE: + if (decoder->hue == ctrl->value) break; - default: - return -EINVAL; - } + decoder->hue = ctrl->value; + bt819_write(decoder, 0x0f, decoder->hue); break; + + default: + return -EINVAL; } + return 0; +} - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; +static int bt819_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct bt819 *decoder = to_bt819(sd); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = decoder->bright; - break; - case V4L2_CID_CONTRAST: - ctrl->value = decoder->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = decoder->sat; - break; - case V4L2_CID_HUE: - ctrl->value = decoder->hue; - break; - default: - return -EINVAL; - } + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; break; - } - default: return -EINVAL; } - return 0; } +static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct bt819 *decoder = to_bt819(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); +} + +static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_core_ops bt819_core_ops = { + .g_chip_ident = bt819_g_chip_ident, + .g_ctrl = bt819_g_ctrl, + .s_ctrl = bt819_s_ctrl, + .queryctrl = bt819_queryctrl, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_tuner_ops bt819_tuner_ops = { + .s_std = bt819_s_std, +}; + +static const struct v4l2_subdev_video_ops bt819_video_ops = { + .s_routing = bt819_s_routing, + .s_stream = bt819_s_stream, + .querystd = bt819_querystd, + .g_input_status = bt819_g_input_status, +}; + +static const struct v4l2_subdev_ops bt819_ops = { + .core = &bt819_core_ops, + .tuner = &bt819_tuner_ops, + .video = &bt819_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int bt819_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i, ver; struct bt819 *decoder; + struct v4l2_subdev *sd; const char *name; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - ver = bt819_read(client, 0x17); + decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); + if (decoder == NULL) + return -ENOMEM; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &bt819_ops); + + ver = bt819_read(decoder, 0x17); switch (ver & 0xf0) { case 0x70: name = "bt819a"; + decoder->ident = V4L2_IDENT_BT819A; break; case 0x60: name = "bt817a"; + decoder->ident = V4L2_IDENT_BT817A; break; case 0x20: name = "bt815a"; + decoder->ident = V4L2_IDENT_BT815A; break; default: - v4l_dbg(1, debug, client, + v4l2_dbg(1, debug, sd, "unknown chip version 0x%02x\n", ver); return -ENODEV; } @@ -473,28 +502,26 @@ static int bt819_probe(struct i2c_client *client, v4l_info(client, "%s found @ 0x%x (%s)\n", name, client->addr << 1, client->adapter->name); - decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); - if (decoder == NULL) - return -ENOMEM; decoder->norm = V4L2_STD_NTSC; decoder->input = 0; decoder->enable = 1; decoder->bright = 0; decoder->contrast = 0xd8; /* 100% of original signal */ decoder->hue = 0; - decoder->sat = 0xfe; /* 100% of original signal */ - decoder->initialized = 0; - i2c_set_clientdata(client, decoder); + decoder->sat = 0xfe; /* 100% of original signal */ - i = bt819_init(client); + i = bt819_init(sd); if (i < 0) - v4l_dbg(1, debug, client, "init status %d\n", i); + v4l2_dbg(1, debug, sd, "init status %d\n", i); return 0; } static int bt819_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_bt819(sd)); return 0; } -- cgit v1.2.3 From 83017bf64bd5809eb60a2381a34d77c854e06e74 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 12:08:07 +0100 Subject: bt819: that delay include is needed after all. From: Hans Verkuil Thanks to Jean Delvare for pointing this out. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt819.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index 5c1ab1c74..4d44df52b 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From d4bc011f6faca5294fb7a32b8fdad9e6a3c29d8e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 12:54:36 +0100 Subject: bt856: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt856.c | 243 +++++++++++++++++++++----------------- 1 file changed, 136 insertions(+), 107 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c index 626019e49..96def6283 100644 --- a/linux/drivers/media/video/bt856.c +++ b/linux/drivers/media/video/bt856.c @@ -34,9 +34,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include "compat.h" @@ -48,42 +48,49 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ #define BT856_REG_OFFSET 0xDA #define BT856_NR_REG 6 struct bt856 { + struct v4l2_subdev sd; unsigned char reg[BT856_NR_REG]; v4l2_std_id norm; }; +static inline struct bt856 *to_bt856(struct v4l2_subdev *sd) +{ + return container_of(sd, struct bt856, sd); +} + /* ----------------------------------------------------------------------- */ -static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value) +static inline int bt856_write(struct bt856 *encoder, u8 reg, u8 value) { - struct bt856 *encoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd); encoder->reg[reg - BT856_REG_OFFSET] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) +static inline int bt856_setbit(struct bt856 *encoder, u8 reg, u8 bit, u8 value) { - struct bt856 *encoder = i2c_get_clientdata(client); - - return bt856_write(client, reg, + return bt856_write(encoder, reg, (encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | (value ? (1 << bit) : 0)); } -static void bt856_dump(struct i2c_client *client) +static void bt856_dump(struct bt856 *encoder) { int i; - struct bt856 *encoder = i2c_get_clientdata(client); - v4l_info(client, "register dump:\n"); + v4l2_info(&encoder->sd, "register dump:\n"); for (i = 0; i < BT856_NR_REG; i += 2) printk(KERN_CONT " %02x", encoder->reg[i]); printk(KERN_CONT "\n"); @@ -91,107 +98,125 @@ static void bt856_dump(struct i2c_client *client) /* ----------------------------------------------------------------------- */ -static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) +static int bt856_init(struct v4l2_subdev *sd, u32 arg) { - struct bt856 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: - /* This is just for testing!!! */ - v4l_dbg(1, debug, client, "init\n"); - bt856_write(client, 0xdc, 0x18); - bt856_write(client, 0xda, 0); - bt856_write(client, 0xde, 0); - - bt856_setbit(client, 0xdc, 3, 1); - //bt856_setbit(client, 0xdc, 6, 0); - bt856_setbit(client, 0xdc, 4, 1); - - if (encoder->norm & V4L2_STD_NTSC) - bt856_setbit(client, 0xdc, 2, 0); - else - bt856_setbit(client, 0xdc, 2, 1); - - bt856_setbit(client, 0xdc, 1, 1); - bt856_setbit(client, 0xde, 4, 0); - bt856_setbit(client, 0xde, 3, 1); - if (debug != 0) - bt856_dump(client); - break; + struct bt856 *encoder = to_bt856(sd); - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id *iarg = arg; - - v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - - if (*iarg & V4L2_STD_NTSC) { - bt856_setbit(client, 0xdc, 2, 0); - } else if (*iarg & V4L2_STD_PAL) { - bt856_setbit(client, 0xdc, 2, 1); - bt856_setbit(client, 0xda, 0, 0); - //bt856_setbit(client, 0xda, 0, 1); - } else { - return -EINVAL; - } - encoder->norm = *iarg; - if (debug != 0) - bt856_dump(client); - break; - } + /* This is just for testing!!! */ + v4l2_dbg(1, debug, sd, "init\n"); + bt856_write(encoder, 0xdc, 0x18); + bt856_write(encoder, 0xda, 0); + bt856_write(encoder, 0xde, 0); - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - v4l_dbg(1, debug, client, "set input %d\n", route->input); - - /* We only have video bus. - * route->input= 0: input is from bt819 - * route->input= 1: input is from ZR36060 */ - switch (route->input) { - case 0: - bt856_setbit(client, 0xde, 4, 0); - bt856_setbit(client, 0xde, 3, 1); - bt856_setbit(client, 0xdc, 3, 1); - bt856_setbit(client, 0xdc, 6, 0); - break; - case 1: - bt856_setbit(client, 0xde, 4, 0); - bt856_setbit(client, 0xde, 3, 1); - bt856_setbit(client, 0xdc, 3, 1); - bt856_setbit(client, 0xdc, 6, 1); - break; - case 2: // Color bar - bt856_setbit(client, 0xdc, 3, 0); - bt856_setbit(client, 0xde, 4, 1); - break; - default: - return -EINVAL; - } - - if (debug != 0) - bt856_dump(client); - break; + bt856_setbit(encoder, 0xdc, 3, 1); + /*bt856_setbit(encoder, 0xdc, 6, 0);*/ + bt856_setbit(encoder, 0xdc, 4, 1); + + if (encoder->norm & V4L2_STD_NTSC) + bt856_setbit(encoder, 0xdc, 2, 0); + else + bt856_setbit(encoder, 0xdc, 2, 1); + + bt856_setbit(encoder, 0xdc, 1, 1); + bt856_setbit(encoder, 0xde, 4, 0); + bt856_setbit(encoder, 0xde, 3, 1); + if (debug != 0) + bt856_dump(encoder); + return 0; +} + +static int bt856_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct bt856 *encoder = to_bt856(sd); + + v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + + if (std & V4L2_STD_NTSC) { + bt856_setbit(encoder, 0xdc, 2, 0); + } else if (std & V4L2_STD_PAL) { + bt856_setbit(encoder, 0xdc, 2, 1); + bt856_setbit(encoder, 0xda, 0, 0); + /*bt856_setbit(encoder, 0xda, 0, 1);*/ + } else { + return -EINVAL; } + encoder->norm = std; + if (debug != 0) + bt856_dump(encoder); + return 0; +} +static int bt856_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct bt856 *encoder = to_bt856(sd); + + v4l2_dbg(1, debug, sd, "set input %d\n", route->input); + + /* We only have video bus. + * route->input= 0: input is from bt819 + * route->input= 1: input is from ZR36060 */ + switch (route->input) { + case 0: + bt856_setbit(encoder, 0xde, 4, 0); + bt856_setbit(encoder, 0xde, 3, 1); + bt856_setbit(encoder, 0xdc, 3, 1); + bt856_setbit(encoder, 0xdc, 6, 0); + break; + case 1: + bt856_setbit(encoder, 0xde, 4, 0); + bt856_setbit(encoder, 0xde, 3, 1); + bt856_setbit(encoder, 0xdc, 3, 1); + bt856_setbit(encoder, 0xdc, 6, 1); + break; + case 2: /* Color bar */ + bt856_setbit(encoder, 0xdc, 3, 0); + bt856_setbit(encoder, 0xde, 4, 1); + break; default: return -EINVAL; } + if (debug != 0) + bt856_dump(encoder); return 0; } +static int bt856_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT856, 0); +} + +static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_core_ops bt856_core_ops = { + .g_chip_ident = bt856_g_chip_ident, + .init = bt856_init, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops bt856_video_ops = { + .s_std_output = bt856_s_std_output, + .s_routing = bt856_s_routing, +}; + +static const struct v4l2_subdev_ops bt856_ops = { + .core = &bt856_core_ops, + .video = &bt856_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int bt856_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct bt856 *encoder; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -203,34 +228,38 @@ static int bt856_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &bt856_ops); encoder->norm = V4L2_STD_NTSC; - i2c_set_clientdata(client, encoder); - bt856_write(client, 0xdc, 0x18); - bt856_write(client, 0xda, 0); - bt856_write(client, 0xde, 0); + bt856_write(encoder, 0xdc, 0x18); + bt856_write(encoder, 0xda, 0); + bt856_write(encoder, 0xde, 0); - bt856_setbit(client, 0xdc, 3, 1); - //bt856_setbit(client, 0xdc, 6, 0); - bt856_setbit(client, 0xdc, 4, 1); + bt856_setbit(encoder, 0xdc, 3, 1); + /*bt856_setbit(encoder, 0xdc, 6, 0);*/ + bt856_setbit(encoder, 0xdc, 4, 1); if (encoder->norm & V4L2_STD_NTSC) - bt856_setbit(client, 0xdc, 2, 0); + bt856_setbit(encoder, 0xdc, 2, 0); else - bt856_setbit(client, 0xdc, 2, 1); + bt856_setbit(encoder, 0xdc, 2, 1); - bt856_setbit(client, 0xdc, 1, 1); - bt856_setbit(client, 0xde, 4, 0); - bt856_setbit(client, 0xde, 3, 1); + bt856_setbit(encoder, 0xdc, 1, 1); + bt856_setbit(encoder, 0xde, 4, 0); + bt856_setbit(encoder, 0xde, 3, 1); if (debug != 0) - bt856_dump(client); + bt856_dump(encoder); return 0; } static int bt856_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_bt856(sd)); return 0; } -- cgit v1.2.3 From 57e7068b395d03b36ee570e151cda28201b9e565 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 15:50:27 +0100 Subject: ks0127: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ks0127.c | 664 +++++++++++++++++-------------------- 1 file changed, 310 insertions(+), 354 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index 3b565c039..8d8048ce8 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -39,8 +39,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include "ks0127.h" #include "compat.h" @@ -49,10 +50,17 @@ MODULE_DESCRIPTION("KS0127 video decoder driver"); MODULE_AUTHOR("Ryan Drake"); MODULE_LICENSE("GPL"); -#define KS_TYPE_UNKNOWN 0 -#define KS_TYPE_0122S 1 -#define KS_TYPE_0127 2 -#define KS_TYPE_0127B 3 +/* Addresses to scan */ +#define I2C_KS0127_ADDON 0xD8 +#define I2C_KS0127_ONBOARD 0xDA + +static unsigned short normal_i2c[] = { + I2C_KS0127_ADDON >> 1, + I2C_KS0127_ONBOARD >> 1, + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; /* ks0127 control registers */ #define KS_STAT 0x00 @@ -198,15 +206,17 @@ struct adjust { }; struct ks0127 { - int format_width; - int format_height; - int cap_width; - int cap_height; + struct v4l2_subdev sd; v4l2_std_id norm; - int ks_type; + int ident; u8 regs[256]; }; +static inline struct ks0127 *to_ks0127(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ks0127, sd); +} + static int debug; /* insmod parameter */ @@ -312,43 +322,45 @@ static void init_reg_defaults(void) */ -static u8 ks0127_read(struct i2c_client *c, u8 reg) +static u8 ks0127_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); char val = 0; struct i2c_msg msgs[] = { - { c->addr, 0, sizeof(reg), ® }, - { c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val } + { client->addr, 0, sizeof(reg), ® }, + { client->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val } }; int ret; - ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs)); + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (ret != ARRAY_SIZE(msgs)) - v4l_dbg(1, debug, c, "read error\n"); + v4l2_dbg(1, debug, sd, "read error\n"); return val; } -static void ks0127_write(struct i2c_client *c, u8 reg, u8 val) +static void ks0127_write(struct v4l2_subdev *sd, u8 reg, u8 val) { - struct ks0127 *ks = i2c_get_clientdata(c); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ks0127 *ks = to_ks0127(sd); char msg[] = { reg, val }; - if (i2c_master_send(c, msg, sizeof(msg)) != sizeof(msg)) - v4l_dbg(1, debug, c, "write error\n"); + if (i2c_master_send(client, msg, sizeof(msg)) != sizeof(msg)) + v4l2_dbg(1, debug, sd, "write error\n"); ks->regs[reg] = val; } /* generic bit-twiddling */ -static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v) +static void ks0127_and_or(struct v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v) { - struct ks0127 *ks = i2c_get_clientdata(client); + struct ks0127 *ks = to_ks0127(sd); u8 val = ks->regs[reg]; val = (val & and_v) | or_v; - ks0127_write(client, reg, val); + ks0127_write(sd, reg, val); } @@ -356,409 +368,353 @@ static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v) /**************************************************************************** * ks0127 private api ****************************************************************************/ -static void ks0127_reset(struct i2c_client *c) +static void ks0127_init(struct v4l2_subdev *sd) { - struct ks0127 *ks = i2c_get_clientdata(c); + struct ks0127 *ks = to_ks0127(sd); u8 *table = reg_defaults; int i; - ks->ks_type = KS_TYPE_UNKNOWN; + ks->ident = V4L2_IDENT_KS0127; - v4l_dbg(1, debug, c, "reset\n"); + v4l2_dbg(1, debug, sd, "reset\n"); msleep(1); /* initialize all registers to known values */ /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */ for (i = 1; i < 33; i++) - ks0127_write(c, i, table[i]); + ks0127_write(sd, i, table[i]); for (i = 35; i < 40; i++) - ks0127_write(c, i, table[i]); + ks0127_write(sd, i, table[i]); for (i = 41; i < 56; i++) - ks0127_write(c, i, table[i]); + ks0127_write(sd, i, table[i]); for (i = 58; i < 64; i++) - ks0127_write(c, i, table[i]); + ks0127_write(sd, i, table[i]); - if ((ks0127_read(c, KS_STAT) & 0x80) == 0) { - ks->ks_type = KS_TYPE_0122S; - v4l_dbg(1, debug, c, "ks0122s found\n"); + if ((ks0127_read(sd, KS_STAT) & 0x80) == 0) { + ks->ident = V4L2_IDENT_KS0122S; + v4l2_dbg(1, debug, sd, "ks0122s found\n"); return; } - switch (ks0127_read(c, KS_CMDE) & 0x0f) { + switch (ks0127_read(sd, KS_CMDE) & 0x0f) { case 0: - ks->ks_type = KS_TYPE_0127; - v4l_dbg(1, debug, c, "ks0127 found\n"); + v4l2_dbg(1, debug, sd, "ks0127 found\n"); break; case 9: - ks->ks_type = KS_TYPE_0127B; - v4l_dbg(1, debug, c, "ks0127B Revision A found\n"); + ks->ident = V4L2_IDENT_KS0127B; + v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n"); break; default: - v4l_dbg(1, debug, c, "unknown revision\n"); + v4l2_dbg(1, debug, sd, "unknown revision\n"); break; } } -static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) +static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct ks0127 *ks = i2c_get_clientdata(c); - struct v4l2_routing *route = arg; - int *iarg = (int *)arg; - v4l2_std_id *istd = arg; - int status; - - if (!ks) - return -ENODEV; - - switch (cmd) { - case VIDIOC_INT_INIT: - v4l_dbg(1, debug, c, "VIDIOC_INT_INIT\n"); - ks0127_reset(c); + struct ks0127 *ks = to_ks0127(sd); + + switch (route->input) { + case KS_INPUT_COMPOSITE_1: + case KS_INPUT_COMPOSITE_2: + case KS_INPUT_COMPOSITE_3: + case KS_INPUT_COMPOSITE_4: + case KS_INPUT_COMPOSITE_5: + case KS_INPUT_COMPOSITE_6: + v4l2_dbg(1, debug, sd, + "VIDIOC_S_INPUT %d: Composite\n", route->input); + /* autodetect 50/60 Hz */ + ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); + /* VSE=0 */ + ks0127_and_or(sd, KS_CMDA, ~0x40, 0x00); + /* set input line */ + ks0127_and_or(sd, KS_CMDB, 0xb0, route->input); + /* non-freerunning mode */ + ks0127_and_or(sd, KS_CMDC, 0x70, 0x0a); + /* analog input */ + ks0127_and_or(sd, KS_CMDD, 0x03, 0x00); + /* enable chroma demodulation */ + ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x00); + /* chroma trap, HYBWR=1 */ + ks0127_and_or(sd, KS_LUMA, 0x00, + (reg_defaults[KS_LUMA])|0x0c); + /* scaler fullbw, luma comb off */ + ks0127_and_or(sd, KS_VERTIA, 0x08, 0x81); + /* manual chroma comb .25 .5 .25 */ + ks0127_and_or(sd, KS_VERTIC, 0x0f, 0x90); + + /* chroma path delay */ + ks0127_and_or(sd, KS_CHROMB, 0x0f, 0x90); + + ks0127_write(sd, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(sd, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(sd, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(sd, KS_UVOFFL, reg_defaults[KS_UVOFFL]); break; - case VIDIOC_INT_S_VIDEO_ROUTING: - switch (route->input) { - case KS_INPUT_COMPOSITE_1: - case KS_INPUT_COMPOSITE_2: - case KS_INPUT_COMPOSITE_3: - case KS_INPUT_COMPOSITE_4: - case KS_INPUT_COMPOSITE_5: - case KS_INPUT_COMPOSITE_6: - v4l_dbg(1, debug, c, - "VIDIOC_S_INPUT %d: Composite\n", *iarg); - /* autodetect 50/60 Hz */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); - /* VSE=0 */ - ks0127_and_or(c, KS_CMDA, ~0x40, 0x00); - /* set input line */ - ks0127_and_or(c, KS_CMDB, 0xb0, *iarg); - /* non-freerunning mode */ - ks0127_and_or(c, KS_CMDC, 0x70, 0x0a); - /* analog input */ - ks0127_and_or(c, KS_CMDD, 0x03, 0x00); - /* enable chroma demodulation */ - ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00); - /* chroma trap, HYBWR=1 */ - ks0127_and_or(c, KS_LUMA, 0x00, - (reg_defaults[KS_LUMA])|0x0c); - /* scaler fullbw, luma comb off */ - ks0127_and_or(c, KS_VERTIA, 0x08, 0x81); - /* manual chroma comb .25 .5 .25 */ - ks0127_and_or(c, KS_VERTIC, 0x0f, 0x90); - - /* chroma path delay */ - ks0127_and_or(c, KS_CHROMB, 0x0f, 0x90); - - ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]); - ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]); - ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]); - ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]); - break; - - case KS_INPUT_SVIDEO_1: - case KS_INPUT_SVIDEO_2: - case KS_INPUT_SVIDEO_3: - v4l_dbg(1, debug, c, - "VIDIOC_S_INPUT %d: S-Video\n", *iarg); - /* autodetect 50/60 Hz */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); - /* VSE=0 */ - ks0127_and_or(c, KS_CMDA, ~0x40, 0x00); - /* set input line */ - ks0127_and_or(c, KS_CMDB, 0xb0, *iarg); - /* non-freerunning mode */ - ks0127_and_or(c, KS_CMDC, 0x70, 0x0a); - /* analog input */ - ks0127_and_or(c, KS_CMDD, 0x03, 0x00); - /* enable chroma demodulation */ - ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00); - ks0127_and_or(c, KS_LUMA, 0x00, - reg_defaults[KS_LUMA]); - /* disable luma comb */ - ks0127_and_or(c, KS_VERTIA, 0x08, - (reg_defaults[KS_VERTIA]&0xf0)|0x01); - ks0127_and_or(c, KS_VERTIC, 0x0f, - reg_defaults[KS_VERTIC]&0xf0); - - ks0127_and_or(c, KS_CHROMB, 0x0f, - reg_defaults[KS_CHROMB]&0xf0); - - ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]); - ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]); - ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]); - ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]); - break; - - case KS_INPUT_YUV656: - v4l_dbg(1, debug, c, - "VIDIOC_S_INPUT 15: YUV656\n"); - if (ks->norm & V4L2_STD_525_60) - /* force 60 Hz */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x03); - else - /* force 50 Hz */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x02); - - ks0127_and_or(c, KS_CMDA, 0xff, 0x40); /* VSE=1 */ - /* set input line and VALIGN */ - ks0127_and_or(c, KS_CMDB, 0xb0, (*iarg | 0x40)); - /* freerunning mode, */ - /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ - ks0127_and_or(c, KS_CMDC, 0x70, 0x87); - /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */ - ks0127_and_or(c, KS_CMDD, 0x03, 0x08); - /* disable chroma demodulation */ - ks0127_and_or(c, KS_CTRACK, 0xcf, 0x30); - /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */ - ks0127_and_or(c, KS_LUMA, 0x00, 0x71); - ks0127_and_or(c, KS_VERTIC, 0x0f, - reg_defaults[KS_VERTIC]&0xf0); - - /* scaler fullbw, luma comb off */ - ks0127_and_or(c, KS_VERTIA, 0x08, 0x81); - - ks0127_and_or(c, KS_CHROMB, 0x0f, - reg_defaults[KS_CHROMB]&0xf0); - - ks0127_and_or(c, KS_CON, 0x00, 0x00); - ks0127_and_or(c, KS_BRT, 0x00, 32); /* spec: 34 */ - /* spec: 229 (e5) */ - ks0127_and_or(c, KS_SAT, 0x00, 0xe8); - ks0127_and_or(c, KS_HUE, 0x00, 0); - - ks0127_and_or(c, KS_UGAIN, 0x00, 238); - ks0127_and_or(c, KS_VGAIN, 0x00, 0x00); - - /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */ - ks0127_and_or(c, KS_UVOFFH, 0x00, 0x4f); - ks0127_and_or(c, KS_UVOFFL, 0x00, 0x00); - break; - - default: - v4l_dbg(1, debug, c, - "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input); - break; - } - - /* hack: CDMLPF sometimes spontaneously switches on; */ - /* force back off */ - ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]); + case KS_INPUT_SVIDEO_1: + case KS_INPUT_SVIDEO_2: + case KS_INPUT_SVIDEO_3: + v4l2_dbg(1, debug, sd, + "VIDIOC_S_INPUT %d: S-Video\n", route->input); + /* autodetect 50/60 Hz */ + ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); + /* VSE=0 */ + ks0127_and_or(sd, KS_CMDA, ~0x40, 0x00); + /* set input line */ + ks0127_and_or(sd, KS_CMDB, 0xb0, route->input); + /* non-freerunning mode */ + ks0127_and_or(sd, KS_CMDC, 0x70, 0x0a); + /* analog input */ + ks0127_and_or(sd, KS_CMDD, 0x03, 0x00); + /* enable chroma demodulation */ + ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x00); + ks0127_and_or(sd, KS_LUMA, 0x00, + reg_defaults[KS_LUMA]); + /* disable luma comb */ + ks0127_and_or(sd, KS_VERTIA, 0x08, + (reg_defaults[KS_VERTIA]&0xf0)|0x01); + ks0127_and_or(sd, KS_VERTIC, 0x0f, + reg_defaults[KS_VERTIC]&0xf0); + + ks0127_and_or(sd, KS_CHROMB, 0x0f, + reg_defaults[KS_CHROMB]&0xf0); + + ks0127_write(sd, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(sd, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(sd, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(sd, KS_UVOFFL, reg_defaults[KS_UVOFFL]); break; - case VIDIOC_S_STD: /* sam This block mixes old and new norm names... */ - /* Set to automatic SECAM/Fsc mode */ - ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); - - ks->norm = *istd; -#if 0 - /* this is untested !! */ - /* It just detects PAL_N/NTSC_M (no special frequencies) */ - /* And you have to set the standard a second time afterwards */ - case VIDEO_MODE_AUTO: - v4l_dbg(1, debug, c, - "VIDIOC_S_STD: AUTO\n"); - - /* The chip determines the format */ - /* based on the current field rate */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); - /* This is wrong for PAL ! As I said, */ - /* you need to set the standard once again !! */ - ks->format_height = 240; - ks->format_width = 704; - break; -#endif - - if (*istd & V4L2_STD_NTSC) { - v4l_dbg(1, debug, c, - "VIDIOC_S_STD: NTSC_M\n"); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); - ks->format_height = 240; - ks->format_width = 704; - } else if (*istd & V4L2_STD_PAL_N) { - v4l_dbg(1, debug, c, - "KS0127_SET_NORM: NTSC_N (fixme)\n"); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); - ks->format_height = 240; - ks->format_width = 704; - } else if (*istd & V4L2_STD_PAL) { - v4l_dbg(1, debug, c, - "VIDIOC_S_STD: PAL_N\n"); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); - ks->format_height = 290; - ks->format_width = 704; - } else if (*istd & V4L2_STD_PAL_M) { - v4l_dbg(1, debug, c, - "KS0127_SET_NORM: PAL_M (fixme)\n"); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); - ks->format_height = 290; - ks->format_width = 704; - } else if (*istd & V4L2_STD_SECAM) { - v4l_dbg(1, debug, c, - "KS0127_SET_NORM: SECAM\n"); - ks->format_height = 290; - ks->format_width = 704; - - /* set to secam autodetection */ - ks0127_and_or(c, KS_CHROMA, 0xdf, 0x20); - ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); - schedule_timeout_interruptible(HZ/10+1); - - /* did it autodetect? */ - if (!(ks0127_read(c, KS_DEMOD) & 0x40)) - /* force to secam mode */ - ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f); - } else { - v4l_dbg(1, debug, c, - "VIDIOC_S_STD: Unknown norm %llx\n", *istd); - } + case KS_INPUT_YUV656: + v4l2_dbg(1, debug, sd, "VIDIOC_S_INPUT 15: YUV656\n"); + if (ks->norm & V4L2_STD_525_60) + /* force 60 Hz */ + ks0127_and_or(sd, KS_CMDA, 0xfc, 0x03); + else + /* force 50 Hz */ + ks0127_and_or(sd, KS_CMDA, 0xfc, 0x02); + + ks0127_and_or(sd, KS_CMDA, 0xff, 0x40); /* VSE=1 */ + /* set input line and VALIGN */ + ks0127_and_or(sd, KS_CMDB, 0xb0, (route->input | 0x40)); + /* freerunning mode, */ + /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ + ks0127_and_or(sd, KS_CMDC, 0x70, 0x87); + /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */ + ks0127_and_or(sd, KS_CMDD, 0x03, 0x08); + /* disable chroma demodulation */ + ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x30); + /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */ + ks0127_and_or(sd, KS_LUMA, 0x00, 0x71); + ks0127_and_or(sd, KS_VERTIC, 0x0f, + reg_defaults[KS_VERTIC]&0xf0); + + /* scaler fullbw, luma comb off */ + ks0127_and_or(sd, KS_VERTIA, 0x08, 0x81); + + ks0127_and_or(sd, KS_CHROMB, 0x0f, + reg_defaults[KS_CHROMB]&0xf0); + + ks0127_and_or(sd, KS_CON, 0x00, 0x00); + ks0127_and_or(sd, KS_BRT, 0x00, 32); /* spec: 34 */ + /* spec: 229 (e5) */ + ks0127_and_or(sd, KS_SAT, 0x00, 0xe8); + ks0127_and_or(sd, KS_HUE, 0x00, 0); + + ks0127_and_or(sd, KS_UGAIN, 0x00, 238); + ks0127_and_or(sd, KS_VGAIN, 0x00, 0x00); + + /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */ + ks0127_and_or(sd, KS_UVOFFH, 0x00, 0x4f); + ks0127_and_or(sd, KS_UVOFFL, 0x00, 0x00); break; - case VIDIOC_QUERYCTRL: - { - return -EINVAL; - } - - case VIDIOC_S_CTRL: - v4l_dbg(1, debug, c, - "VIDIOC_S_CTRL: not yet supported\n"); - return -EINVAL; - - case VIDIOC_G_CTRL: - v4l_dbg(1, debug, c, - "VIDIOC_G_CTRL: not yet supported\n"); - return -EINVAL; - - /* sam todo: KS0127_SET_BRIGHTNESS: Merge into VIDIOC_S_CTRL */ - /* sam todo: KS0127_SET_CONTRAST: Merge into VIDIOC_S_CTRL */ - /* sam todo: KS0127_SET_HUE: Merge into VIDIOC_S_CTRL? */ - /* sam todo: KS0127_SET_SATURATION: Merge into VIDIOC_S_CTRL */ - /* sam todo: KS0127_SET_AGC_MODE: */ - /* sam todo: KS0127_SET_AGC: */ - /* sam todo: KS0127_SET_CHROMA_MODE: */ - /* sam todo: KS0127_SET_PIXCLK_MODE: */ - /* sam todo: KS0127_SET_GAMMA_MODE: */ - /* sam todo: KS0127_SET_UGAIN: */ - /* sam todo: KS0127_SET_VGAIN: */ - /* sam todo: KS0127_SET_INVALY: */ - /* sam todo: KS0127_SET_INVALU: */ - /* sam todo: KS0127_SET_INVALV: */ - /* sam todo: KS0127_SET_UNUSEY: */ - /* sam todo: KS0127_SET_UNUSEU: */ - /* sam todo: KS0127_SET_UNUSEV: */ - /* sam todo: KS0127_SET_VSALIGN_MODE: */ - - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - { - int enable = cmd == VIDIOC_STREAMON; - - if (enable) { - v4l_dbg(1, debug, c, - "VIDIOC_STREAMON\n"); - /* All output pins on */ - ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30); - /* Obey the OEN pin */ - ks0127_and_or(c, KS_CDEM, 0x7f, 0x00); - } else { - v4l_dbg(1, debug, c, - "VIDIOC_STREAMOFF\n"); - /* Video output pins off */ - ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00); - /* Ignore the OEN pin */ - ks0127_and_or(c, KS_CDEM, 0x7f, 0x80); - } + default: + v4l2_dbg(1, debug, sd, + "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input); break; } - /* sam todo: KS0127_SET_OUTPUT_MODE: */ - /* sam todo: KS0127_SET_WIDTH: */ - /* sam todo: KS0127_SET_HEIGHT: */ - /* sam todo: KS0127_SET_HSCALE: */ - - case VIDIOC_QUERYSTD: - case VIDIOC_INT_G_INPUT_STATUS: { - int stat = V4L2_IN_ST_NO_SIGNAL; - v4l2_std_id std = V4L2_STD_ALL; - v4l_dbg(1, debug, c, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); - status = ks0127_read(c, KS_STAT); - if (!(status & 0x20)) /* NOVID not set */ - stat = 0; - if (!(status & 0x01)) /* CLOCK set */ - stat |= V4L2_IN_ST_NO_COLOR; - if ((status & 0x08)) /* PALDET set */ - std = V4L2_STD_PAL; - else - std = V4L2_STD_NTSC; - if (cmd == VIDIOC_QUERYSTD) - *istd = std; - else - *iarg = stat; - break; + /* hack: CDMLPF sometimes spontaneously switches on; */ + /* force back off */ + ks0127_write(sd, KS_DEMOD, reg_defaults[KS_DEMOD]); + return 0; +} + +static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct ks0127 *ks = to_ks0127(sd); + + /* Set to automatic SECAM/Fsc mode */ + ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x00); + + ks->norm = std; + if (std & V4L2_STD_NTSC) { + v4l2_dbg(1, debug, sd, + "VIDIOC_S_STD: NTSC_M\n"); + ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20); + } else if (std & V4L2_STD_PAL_N) { + v4l2_dbg(1, debug, sd, + "KS0127_SET_NORM: NTSC_N (fixme)\n"); + ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40); + } else if (std & V4L2_STD_PAL) { + v4l2_dbg(1, debug, sd, + "VIDIOC_S_STD: PAL_N\n"); + ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20); + } else if (std & V4L2_STD_PAL_M) { + v4l2_dbg(1, debug, sd, + "KS0127_SET_NORM: PAL_M (fixme)\n"); + ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40); + } else if (std & V4L2_STD_SECAM) { + v4l2_dbg(1, debug, sd, + "KS0127_SET_NORM: SECAM\n"); + + /* set to secam autodetection */ + ks0127_and_or(sd, KS_CHROMA, 0xdf, 0x20); + ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x00); + schedule_timeout_interruptible(HZ/10+1); + + /* did it autodetect? */ + if (!(ks0127_read(sd, KS_DEMOD) & 0x40)) + /* force to secam mode */ + ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x0f); + } else { + v4l2_dbg(1, debug, sd, + "VIDIOC_S_STD: Unknown norm %llx\n", std); } + return 0; +} - /* Catch any unknown command */ - default: - v4l_dbg(1, debug, c, "unknown: 0x%08x\n", cmd); - return -EINVAL; +static int ks0127_s_stream(struct v4l2_subdev *sd, int enable) +{ + v4l2_dbg(1, debug, sd, "s_stream(%d)\n", enable); + if (enable) { + /* All output pins on */ + ks0127_and_or(sd, KS_OFMTA, 0xcf, 0x30); + /* Obey the OEN pin */ + ks0127_and_or(sd, KS_CDEM, 0x7f, 0x00); + } else { + /* Video output pins off */ + ks0127_and_or(sd, KS_OFMTA, 0xcf, 0x00); + /* Ignore the OEN pin */ + ks0127_and_or(sd, KS_CDEM, 0x7f, 0x80); } return 0; } +static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) +{ + int stat = V4L2_IN_ST_NO_SIGNAL; + u8 status; + v4l2_std_id std = V4L2_STD_ALL; + + v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); + status = ks0127_read(sd, KS_STAT); + if (!(status & 0x20)) /* NOVID not set */ + stat = 0; + if (!(status & 0x01)) /* CLOCK set */ + stat |= V4L2_IN_ST_NO_COLOR; + if ((status & 0x08)) /* PALDET set */ + std = V4L2_STD_PAL; + else + std = V4L2_STD_NTSC; + if (pstd) + *pstd = std; + if (pstatus) + *pstatus = stat; + return 0; +} -/* Addresses to scan */ -#define I2C_KS0127_ADDON 0xD8 -#define I2C_KS0127_ONBOARD 0xDA +static int ks0127_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + return ks0127_status(sd, NULL, std); +} -static unsigned short normal_i2c[] = { - I2C_KS0127_ADDON >> 1, - I2C_KS0127_ONBOARD >> 1, - I2C_CLIENT_END +static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + return ks0127_status(sd, status, NULL); +} + +static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ks0127 *ks = to_ks0127(sd); + + return v4l2_chip_ident_i2c_client(client, chip, ks->ident, 0); +} + +static int ks0127_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops ks0127_core_ops = { + .g_chip_ident = ks0127_g_chip_ident, }; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_tuner_ops ks0127_tuner_ops = { + .s_std = ks0127_s_std, +}; + +static const struct v4l2_subdev_video_ops ks0127_video_ops = { + .s_routing = ks0127_s_routing, + .s_stream = ks0127_s_stream, + .querystd = ks0127_querystd, + .g_input_status = ks0127_g_input_status, +}; + +static const struct v4l2_subdev_ops ks0127_ops = { + .core = &ks0127_core_ops, + .tuner = &ks0127_tuner_ops, + .video = &ks0127_video_ops, +}; + +/* ----------------------------------------------------------------------- */ -static int ks0127_probe(struct i2c_client *c, const struct i2c_device_id *id) + +static int ks0127_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ks0127 *ks; + struct v4l2_subdev *sd; - v4l_info(c, "%s chip found @ 0x%x (%s)\n", - c->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board", - c->addr << 1, c->adapter->name); + v4l_info(client, "%s chip found @ 0x%x (%s)\n", + client->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board", + client->addr << 1, client->adapter->name); ks = kzalloc(sizeof(*ks), GFP_KERNEL); if (ks == NULL) return -ENOMEM; - - i2c_set_clientdata(c, ks); - - ks->ks_type = KS_TYPE_UNKNOWN; + sd = &ks->sd; + v4l2_i2c_subdev_init(sd, client, &ks0127_ops); /* power up */ init_reg_defaults(); - ks0127_write(c, KS_CMDA, 0x2c); + ks0127_write(sd, KS_CMDA, 0x2c); mdelay(10); /* reset the device */ - ks0127_reset(c); + ks0127_init(sd); return 0; } -static int ks0127_remove(struct i2c_client *c) +static int ks0127_remove(struct i2c_client *client) { - struct ks0127 *ks = i2c_get_clientdata(c); - - ks0127_write(c, KS_OFMTA, 0x20); /* tristate */ - ks0127_write(c, KS_CMDA, 0x2c | 0x80); /* power down */ + struct v4l2_subdev *sd = i2c_get_clientdata(client); - kfree(ks); + v4l2_device_unregister_subdev(sd); + ks0127_write(sd, KS_OFMTA, 0x20); /* tristate */ + ks0127_write(sd, KS_CMDA, 0x2c | 0x80); /* power down */ + kfree(to_ks0127(sd)); return 0; } -- cgit v1.2.3 From 72ea23067f1015a0c08119b4dcc86b42d69f2f6c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 15:51:16 +0100 Subject: ks0127: add supported ks0127 variants to the i2c device list. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ks0127.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index 8d8048ce8..309f61ca4 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -726,6 +726,8 @@ static int ks0127_legacy_probe(struct i2c_adapter *adapter) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id ks0127_id[] = { { "ks0127", 0 }, + { "ks0127b", 0 }, + { "ks0122s", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ks0127_id); -- cgit v1.2.3 From 656b3320294aa88df2d058f03dc1043185a14f89 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 16:24:27 +0100 Subject: saa7110: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7110.c | 464 +++++++++++++++++++----------------- 1 file changed, 248 insertions(+), 216 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index 147c36a71..132ef1812 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -33,9 +33,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include "compat.h" @@ -43,6 +43,10 @@ MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); MODULE_AUTHOR("Pauline Middelink"); MODULE_LICENSE("GPL"); +static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); @@ -53,6 +57,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define SAA7110_NR_REG 0x35 struct saa7110 { + struct v4l2_subdev sd; u8 reg[SAA7110_NR_REG]; v4l2_std_id norm; @@ -66,20 +71,28 @@ struct saa7110 { wait_queue_head_t wq; }; +static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa7110, sd); +} + /* ----------------------------------------------------------------------- */ /* I2C support functions */ /* ----------------------------------------------------------------------- */ -static int saa7110_write(struct i2c_client *client, u8 reg, u8 value) +static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value) { - struct saa7110 *decoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7110 *decoder = to_saa7110(sd); decoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsigned int len) +static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7110 *decoder = to_saa7110(sd); int ret = -1; u8 reg = *data; /* first register to write to */ @@ -90,15 +103,13 @@ static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsign /* the saa7110 has an autoincrement function, use it if * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - struct saa7110 *decoder = i2c_get_clientdata(client); - ret = i2c_master_send(client, data, len); /* Cache the written data */ memcpy(decoder->reg + reg, data + 1, len - 1); } else { for (++data, --len; len; len--) { - ret = saa7110_write(client, reg++, *data++); + ret = saa7110_write(sd, reg++, *data++); if (ret < 0) break; } @@ -107,8 +118,10 @@ static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsign return ret; } -static inline int saa7110_read(struct i2c_client *client) +static inline int saa7110_read(struct v4l2_subdev *sd) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte(client); } @@ -116,11 +129,11 @@ static inline int saa7110_read(struct i2c_client *client) /* SAA7110 functions */ /* ----------------------------------------------------------------------- */ -#define FRESP_06H_COMPST 0x03 //0x13 -#define FRESP_06H_SVIDEO 0x83 //0xC0 +#define FRESP_06H_COMPST 0x03 /*0x13*/ +#define FRESP_06H_SVIDEO 0x83 /*0xC0*/ -static int saa7110_selmux(struct i2c_client *client, int chan) +static int saa7110_selmux(struct v4l2_subdev *sd, int chan) { static const unsigned char modes[9][8] = { /* mode 0 */ @@ -151,17 +164,17 @@ static int saa7110_selmux(struct i2c_client *client, int chan) {FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21} }; - struct saa7110 *decoder = i2c_get_clientdata(client); + struct saa7110 *decoder = to_saa7110(sd); const unsigned char *ptr = modes[chan]; - saa7110_write(client, 0x06, ptr[0]); /* Luminance control */ - saa7110_write(client, 0x20, ptr[1]); /* Analog Control #1 */ - saa7110_write(client, 0x21, ptr[2]); /* Analog Control #2 */ - saa7110_write(client, 0x22, ptr[3]); /* Mixer Control #1 */ - saa7110_write(client, 0x2C, ptr[4]); /* Mixer Control #2 */ - saa7110_write(client, 0x30, ptr[5]); /* ADCs gain control */ - saa7110_write(client, 0x31, ptr[6]); /* Mixer Control #3 */ - saa7110_write(client, 0x21, ptr[7]); /* Analog Control #2 */ + saa7110_write(sd, 0x06, ptr[0]); /* Luminance control */ + saa7110_write(sd, 0x20, ptr[1]); /* Analog Control #1 */ + saa7110_write(sd, 0x21, ptr[2]); /* Analog Control #2 */ + saa7110_write(sd, 0x22, ptr[3]); /* Mixer Control #1 */ + saa7110_write(sd, 0x2C, ptr[4]); /* Mixer Control #2 */ + saa7110_write(sd, 0x30, ptr[5]); /* ADCs gain control */ + saa7110_write(sd, 0x31, ptr[6]); /* Mixer Control #3 */ + saa7110_write(sd, 0x21, ptr[7]); /* Analog Control #2 */ decoder->input = chan; return 0; @@ -177,248 +190,263 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = { /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02 }; -static v4l2_std_id determine_norm(struct i2c_client *client) +static v4l2_std_id determine_norm(struct v4l2_subdev *sd) { DEFINE_WAIT(wait); - struct saa7110 *decoder = i2c_get_clientdata(client); + struct saa7110 *decoder = to_saa7110(sd); int status; /* mode changed, start automatic detection */ - saa7110_write_block(client, initseq, sizeof(initseq)); - saa7110_selmux(client, decoder->input); + saa7110_write_block(sd, initseq, sizeof(initseq)); + saa7110_selmux(sd, decoder->input); prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(250)); finish_wait(&decoder->wq, &wait); - status = saa7110_read(client); + status = saa7110_read(sd); if (status & 0x40) { - v4l_dbg(1, debug, client, "status=0x%02x (no signal)\n", status); - return decoder->norm; // no change + v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status); + return decoder->norm; /* no change*/ } if ((status & 3) == 0) { - saa7110_write(client, 0x06, 0x83); + saa7110_write(sd, 0x06, 0x83); if (status & 0x20) { - v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status); - //saa7110_write(client,0x2E,0x81); + v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status); + /*saa7110_write(sd,0x2E,0x81);*/ return V4L2_STD_NTSC; } - v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status); - //saa7110_write(client,0x2E,0x9A); + v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status); + /*saa7110_write(sd,0x2E,0x9A);*/ return V4L2_STD_PAL; } - //saa7110_write(client,0x06,0x03); + /*saa7110_write(sd,0x06,0x03);*/ if (status & 0x20) { /* 60Hz */ - v4l_dbg(1, debug, client, "status=0x%02x (NTSC)\n", status); - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x50); - saa7110_write(client, 0x11, 0x2C); - //saa7110_write(client,0x2E,0x81); + v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)\n", status); + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x50); + saa7110_write(sd, 0x11, 0x2C); + /*saa7110_write(sd,0x2E,0x81);*/ return V4L2_STD_NTSC; } /* 50Hz -> PAL/SECAM */ - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x10); - saa7110_write(client, 0x11, 0x59); - //saa7110_write(client,0x2E,0x9A); + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x10); + saa7110_write(sd, 0x11, 0x59); + /*saa7110_write(sd,0x2E,0x9A);*/ prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(250)); finish_wait(&decoder->wq, &wait); - status = saa7110_read(client); + status = saa7110_read(sd); if ((status & 0x03) == 0x01) { - v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status); - saa7110_write(client, 0x0D, 0x87); + v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status); + saa7110_write(sd, 0x0D, 0x87); return V4L2_STD_SECAM; } - v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status); + v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status); return V4L2_STD_PAL; } -static int -saa7110_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus) { - struct saa7110 *decoder = i2c_get_clientdata(client); - struct v4l2_routing *route = arg; - v4l2_std_id std; - int v; - - switch (cmd) { - case VIDIOC_INT_INIT: - //saa7110_write_block(client, initseq, sizeof(initseq)); - break; + struct saa7110 *decoder = to_saa7110(sd); + int res = V4L2_IN_ST_NO_SIGNAL; + int status = saa7110_read(sd); + + v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n", + status, decoder->norm); + if (!(status & 0x40)) + res = 0; + if (!(status & 0x03)) + res |= V4L2_IN_ST_NO_COLOR; + + *pstatus = res; + return 0; +} - case VIDIOC_INT_G_INPUT_STATUS: - { - int res = V4L2_IN_ST_NO_SIGNAL; - int status; +static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + *(v4l2_std_id *)std = determine_norm(sd); + return 0; +} - status = saa7110_read(client); - v4l_dbg(1, debug, client, "status=0x%02x norm=%llx\n", - status, decoder->norm); - if (!(status & 0x40)) - res = 0; - if (!(status & 0x03)) - res |= V4L2_IN_ST_NO_COLOR; +static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct saa7110 *decoder = to_saa7110(sd); + + if (decoder->norm != std) { + decoder->norm = std; + /*saa7110_write(sd, 0x06, 0x03);*/ + if (std & V4L2_STD_NTSC) { + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x50); + saa7110_write(sd, 0x11, 0x2C); + /*saa7110_write(sd, 0x2E, 0x81);*/ + v4l2_dbg(1, debug, sd, "switched to NTSC\n"); + } else if (std & V4L2_STD_PAL) { + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x10); + saa7110_write(sd, 0x11, 0x59); + /*saa7110_write(sd, 0x2E, 0x9A);*/ + v4l2_dbg(1, debug, sd, "switched to PAL\n"); + } else if (std & V4L2_STD_SECAM) { + saa7110_write(sd, 0x0D, 0x87); + saa7110_write(sd, 0x0F, 0x10); + saa7110_write(sd, 0x11, 0x59); + /*saa7110_write(sd, 0x2E, 0x9A);*/ + v4l2_dbg(1, debug, sd, "switched to SECAM\n"); + } else { + return -EINVAL; + } + } + return 0; +} - *(int *) arg = res; - break; +static int saa7110_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct saa7110 *decoder = to_saa7110(sd); + + if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) { + v4l2_dbg(1, debug, sd, "input=%d not available\n", route->input); + return -EINVAL; } + if (decoder->input != route->input) { + saa7110_selmux(sd, route->input); + v4l2_dbg(1, debug, sd, "switched to input=%d\n", route->input); + } + return 0; +} - case VIDIOC_QUERYSTD: - { - *(v4l2_std_id *)arg = determine_norm(client); - break; +static int saa7110_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct saa7110 *decoder = to_saa7110(sd); + + if (decoder->enable != enable) { + decoder->enable = enable; + saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80); + v4l2_dbg(1, debug, sd, "YUV %s\n", enable ? "on" : "off"); } + return 0; +} - case VIDIOC_S_STD: - std = *(v4l2_std_id *) arg; - if (decoder->norm != std) { - decoder->norm = std; - //saa7110_write(client, 0x06, 0x03); - if (std & V4L2_STD_NTSC) { - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x50); - saa7110_write(client, 0x11, 0x2C); - //saa7110_write(client, 0x2E, 0x81); - v4l_dbg(1, debug, client, "switched to NTSC\n"); - } else if (std & V4L2_STD_PAL) { - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x10); - saa7110_write(client, 0x11, 0x59); - //saa7110_write(client, 0x2E, 0x9A); - v4l_dbg(1, debug, client, "switched to PAL\n"); - } else if (std & V4L2_STD_SECAM) { - saa7110_write(client, 0x0D, 0x87); - saa7110_write(client, 0x0F, 0x10); - saa7110_write(client, 0x11, 0x59); - //saa7110_write(client, 0x2E, 0x9A); - v4l_dbg(1, debug, client, "switched to SECAM\n"); - } else { - return -EINVAL; - } - } - break; +static int saa7110_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill_std(qc); + default: + return -EINVAL; + } + return 0; +} - case VIDIOC_INT_S_VIDEO_ROUTING: - if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) { - v4l_dbg(1, debug, client, "input=%d not available\n", route->input); - return -EINVAL; - } - if (decoder->input != route->input) { - saa7110_selmux(client, route->input); - v4l_dbg(1, debug, client, "switched to input=%d\n", route->input); - } +static int saa7110_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct saa7110 *decoder = to_saa7110(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; break; + default: + return -EINVAL; + } + return 0; +} - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - v = cmd == VIDIOC_STREAMON; - if (decoder->enable != v) { - decoder->enable = v; - saa7110_write(client, 0x0E, v ? 0x18 : 0x80); - v4l_dbg(1, debug, client, "YUV %s\n", v ? "on" : "off"); +static int saa7110_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct saa7110 *decoder = to_saa7110(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + saa7110_write(sd, 0x19, decoder->bright); } break; - - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); - default: - return -EINVAL; + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + decoder->contrast = ctrl->value; + saa7110_write(sd, 0x13, decoder->contrast); } break; - } - - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = decoder->bright; - break; - case V4L2_CID_CONTRAST: - ctrl->value = decoder->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = decoder->sat; - break; - case V4L2_CID_HUE: - ctrl->value = decoder->hue; - break; - default: - return -EINVAL; + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + saa7110_write(sd, 0x12, decoder->sat); } break; - } - - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if (decoder->bright != ctrl->value) { - decoder->bright = ctrl->value; - saa7110_write(client, 0x19, decoder->bright); - } - break; - case V4L2_CID_CONTRAST: - if (decoder->contrast != ctrl->value) { - decoder->contrast = ctrl->value; - saa7110_write(client, 0x13, decoder->contrast); - } - break; - case V4L2_CID_SATURATION: - if (decoder->sat != ctrl->value) { - decoder->sat = ctrl->value; - saa7110_write(client, 0x12, decoder->sat); - } - break; - case V4L2_CID_HUE: - if (decoder->hue != ctrl->value) { - decoder->hue = ctrl->value; - saa7110_write(client, 0x07, decoder->hue); - } - break; - default: - return -EINVAL; + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + saa7110_write(sd, 0x07, decoder->hue); } break; - } - default: - v4l_dbg(1, debug, client, "unknown command %08x\n", cmd); return -EINVAL; } return 0; } +static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0); +} + +static int saa7110_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ +static const struct v4l2_subdev_core_ops saa7110_core_ops = { + .g_chip_ident = saa7110_g_chip_ident, + .g_ctrl = saa7110_g_ctrl, + .s_ctrl = saa7110_s_ctrl, + .queryctrl = saa7110_queryctrl, +}; -static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_tuner_ops saa7110_tuner_ops = { + .s_std = saa7110_s_std, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops saa7110_video_ops = { + .s_routing = saa7110_s_routing, + .s_stream = saa7110_s_stream, + .querystd = saa7110_querystd, + .g_input_status = saa7110_g_input_status, +}; + +static const struct v4l2_subdev_ops saa7110_ops = { + .core = &saa7110_core_ops, + .tuner = &saa7110_tuner_ops, + .video = &saa7110_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int saa7110_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct saa7110 *decoder; + struct v4l2_subdev *sd; int rv; /* Check if the adapter supports the needed features */ @@ -432,6 +460,8 @@ static int saa7110_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); if (!decoder) return -ENOMEM; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &saa7110_ops); decoder->norm = V4L2_STD_PAL; decoder->input = 0; decoder->enable = 1; @@ -440,30 +470,29 @@ static int saa7110_probe(struct i2c_client *client, decoder->hue = 32768; decoder->sat = 32768; init_waitqueue_head(&decoder->wq); - i2c_set_clientdata(client, decoder); - rv = saa7110_write_block(client, initseq, sizeof(initseq)); + rv = saa7110_write_block(sd, initseq, sizeof(initseq)); if (rv < 0) { - v4l_dbg(1, debug, client, "init status %d\n", rv); + v4l2_dbg(1, debug, sd, "init status %d\n", rv); } else { int ver, status; - saa7110_write(client, 0x21, 0x10); - saa7110_write(client, 0x0e, 0x18); - saa7110_write(client, 0x0D, 0x04); - ver = saa7110_read(client); - saa7110_write(client, 0x0D, 0x06); - //mdelay(150); - status = saa7110_read(client); - v4l_dbg(1, debug, client, "version %x, status=0x%02x\n", + saa7110_write(sd, 0x21, 0x10); + saa7110_write(sd, 0x0e, 0x18); + saa7110_write(sd, 0x0D, 0x04); + ver = saa7110_read(sd); + saa7110_write(sd, 0x0D, 0x06); + /*mdelay(150);*/ + status = saa7110_read(sd); + v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n", ver, status); - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x10); - saa7110_write(client, 0x11, 0x59); - //saa7110_write(client, 0x2E, 0x9A); + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x10); + saa7110_write(sd, 0x11, 0x59); + /*saa7110_write(sd, 0x2E, 0x9A);*/ } - //saa7110_selmux(client,0); - //determine_norm(client); + /*saa7110_selmux(sd,0);*/ + /*determine_norm(sd);*/ /* setup and implicit mode 0 select has been performed */ return 0; @@ -471,7 +500,10 @@ static int saa7110_probe(struct i2c_client *client, static int saa7110_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_saa7110(sd)); return 0; } -- cgit v1.2.3 From 02dd21096ab9d9d92f3531bc72dfe55cf3186d41 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 17:24:47 +0100 Subject: saa7185: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7185.c | 217 ++++++++++++++++++++---------------- 1 file changed, 119 insertions(+), 98 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c index 08cc04138..4c20f0377 100644 --- a/linux/drivers/media/video/saa7185.c +++ b/linux/drivers/media/video/saa7185.c @@ -30,9 +30,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include "compat.h" @@ -40,42 +40,52 @@ MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ struct saa7185 { + struct v4l2_subdev sd; unsigned char reg[128]; v4l2_std_id norm; - int bright; - int contrast; - int hue; - int sat; }; +static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa7185, sd); +} + /* ----------------------------------------------------------------------- */ -static inline int saa7185_read(struct i2c_client *client) +static inline int saa7185_read(struct v4l2_subdev *sd) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte(client); } -static int saa7185_write(struct i2c_client *client, u8 reg, u8 value) +static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value) { - struct saa7185 *encoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7185 *encoder = to_saa7185(sd); - v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value); + v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value); encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static int saa7185_write_block(struct i2c_client *client, +static int saa7185_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7185 *encoder = to_saa7185(sd); int ret = -1; u8 reg; @@ -83,7 +93,6 @@ static int saa7185_write_block(struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct saa7185 *encoder = i2c_get_clientdata(client); u8 block_data[32]; int block_len; @@ -104,7 +113,7 @@ static int saa7185_write_block(struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - ret = saa7185_write(client, reg, *data++); + ret = saa7185_write(sd, reg, *data++); if (ret < 0) break; len -= 2; @@ -213,101 +222,111 @@ static const unsigned char init_ntsc[] = { 0x66, 0x21, /* FSC3 */ }; -static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) + +static int saa7185_init(struct v4l2_subdev *sd, u32 val) +{ + struct saa7185 *encoder = to_saa7185(sd); + + saa7185_write_block(sd, init_common, sizeof(init_common)); + if (encoder->norm & V4L2_STD_NTSC) + saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); + else + saa7185_write_block(sd, init_pal, sizeof(init_pal)); + return 0; +} + +static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct saa7185 *encoder = to_saa7185(sd); + + if (std & V4L2_STD_NTSC) + saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); + else if (std & V4L2_STD_PAL) + saa7185_write_block(sd, init_pal, sizeof(init_pal)); + else + return -EINVAL; + encoder->norm = std; + return 0; +} + +static int saa7185_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct saa7185 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: - saa7185_write_block(client, init_common, - sizeof(init_common)); - if (encoder->norm & V4L2_STD_NTSC) - saa7185_write_block(client, init_ntsc, - sizeof(init_ntsc)); - else - saa7185_write_block(client, init_pal, - sizeof(init_pal)); + struct saa7185 *encoder = to_saa7185(sd); + + /* RJ: route->input = 0: input is from SA7111 + route->input = 1: input is from ZR36060 */ + + switch (route->input) { + case 0: + /* turn off colorbar */ + saa7185_write(sd, 0x3a, 0x0f); + /* Switch RTCE to 1 */ + saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); + saa7185_write(sd, 0x6e, 0x01); break; - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id *iarg = arg; - - //saa7185_write_block(client, init_common, sizeof(init_common)); - - if (*iarg & V4L2_STD_NTSC) - saa7185_write_block(client, init_ntsc, - sizeof(init_ntsc)); - else if (*iarg & V4L2_STD_PAL) - saa7185_write_block(client, init_pal, - sizeof(init_pal)); - else - return -EINVAL; - encoder->norm = *iarg; + case 1: + /* turn off colorbar */ + saa7185_write(sd, 0x3a, 0x0f); + /* Switch RTCE to 0 */ + saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); + /* SW: a slight sync problem... */ + saa7185_write(sd, 0x6e, 0x00); break; - } - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - /* RJ: route->input = 0: input is from SA7111 - route->input = 1: input is from ZR36060 */ - - switch (route->input) { - case 0: - /* turn off colorbar */ - saa7185_write(client, 0x3a, 0x0f); - /* Switch RTCE to 1 */ - saa7185_write(client, 0x61, - (encoder->reg[0x61] & 0xf7) | 0x08); - saa7185_write(client, 0x6e, 0x01); - break; - - case 1: - /* turn off colorbar */ - saa7185_write(client, 0x3a, 0x0f); - /* Switch RTCE to 0 */ - saa7185_write(client, 0x61, - (encoder->reg[0x61] & 0xf7) | 0x00); - /* SW: a slight sync problem... */ - saa7185_write(client, 0x6e, 0x00); - break; - - case 2: - /* turn on colorbar */ - saa7185_write(client, 0x3a, 0x8f); - /* Switch RTCE to 0 */ - saa7185_write(client, 0x61, - (encoder->reg[0x61] & 0xf7) | 0x08); - /* SW: a slight sync problem... */ - saa7185_write(client, 0x6e, 0x01); - break; - - default: - return -EINVAL; - } + case 2: + /* turn on colorbar */ + saa7185_write(sd, 0x3a, 0x8f); + /* Switch RTCE to 0 */ + saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); + /* SW: a slight sync problem... */ + saa7185_write(sd, 0x6e, 0x01); break; - } default: return -EINVAL; } - return 0; } +static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0); +} + +static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_core_ops saa7185_core_ops = { + .g_chip_ident = saa7185_g_chip_ident, + .init = saa7185_init, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops saa7185_video_ops = { + .s_std_output = saa7185_s_std_output, + .s_routing = saa7185_s_routing, +}; + +static const struct v4l2_subdev_ops saa7185_ops = { + .core = &saa7185_core_ops, + .video = &saa7185_video_ops, +}; + + +/* ----------------------------------------------------------------------- */ static int saa7185_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i; struct saa7185 *encoder; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -320,26 +339,28 @@ static int saa7185_probe(struct i2c_client *client, if (encoder == NULL) return -ENOMEM; encoder->norm = V4L2_STD_NTSC; - i2c_set_clientdata(client, encoder); + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &saa7185_ops); - i = saa7185_write_block(client, init_common, sizeof(init_common)); + i = saa7185_write_block(sd, init_common, sizeof(init_common)); if (i >= 0) - i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); + i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); if (i < 0) - v4l_dbg(1, debug, client, "init error %d\n", i); + v4l2_dbg(1, debug, sd, "init error %d\n", i); else - v4l_dbg(1, debug, client, "revision 0x%x\n", - saa7185_read(client) >> 5); + v4l2_dbg(1, debug, sd, "revision 0x%x\n", + saa7185_read(sd) >> 5); return 0; } static int saa7185_remove(struct i2c_client *client) { - struct saa7185 *encoder = i2c_get_clientdata(client); - - saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ - //saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa7185 *encoder = to_saa7185(sd); + v4l2_device_unregister_subdev(sd); + /* SW: output off is active */ + saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40); kfree(encoder); return 0; } -- cgit v1.2.3 From 0992bac9732a651a2024c68cdf87bcd54fa1e381 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 19 Feb 2009 16:41:56 +0000 Subject: em28xx: register device to soundcard for sysfs From: Nicola Soranzo As explained in "Writing an ALSA driver" (T. Iwai), audio drivers should set the struct device for the card before registering the card instance. This will add the correct /sys/class/sound/cardN/device symlink, so HAL can see the device and ConsoleKit sets its ACL permissions for the logged-in user. For em28xx audio capture cards found e.g. in Hauppauge WinTV-HVR-900 (R2), this patch fixes errors like: ALSA lib pcm_hw.c:1429:(_snd_pcm_hw_open) Invalid value for card Error opening audio: Permission denied when running mplayer as a normal user. Priority: normal Signed-off-by: Nicola Soranzo Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-audio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index bfa3986f5..eb49a1364 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -560,6 +560,8 @@ static int em28xx_audio_init(struct em28xx *dev) pcm->info_flags = 0; pcm->private_data = dev; strcpy(pcm->name, "Empia 28xx Capture"); + + snd_card_set_dev(card, &dev->udev->dev); strcpy(card->driver, "Empia Em28xx Audio"); strcpy(card->shortname, "Em28xx Audio"); strcpy(card->longname, "Empia Em28xx Audio"); -- cgit v1.2.3 From e52ceec1d1011cce4b998d43a0375c36d6adfccf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 18:36:53 +0100 Subject: vpx3220: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vpx3220.c | 511 +++++++++++++++++++----------------- 1 file changed, 269 insertions(+), 242 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index 2487f8fe2..1f250229c 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -24,11 +24,10 @@ #include #include #include -#include -#include -#include #include -#include +#include +#include +#include #include "compat.h" MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); @@ -39,14 +38,20 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + #define VPX_TIMEOUT_COUNT 10 /* ----------------------------------------------------------------------- */ struct vpx3220 { + struct v4l2_subdev sd; unsigned char reg[255]; v4l2_std_id norm; + int ident; int input; int enable; int bright; @@ -55,30 +60,38 @@ struct vpx3220 { int sat; }; +static inline struct vpx3220 *to_vpx3220(struct v4l2_subdev *sd) +{ + return container_of(sd, struct vpx3220, sd); +} + static char *inputs[] = { "internal", "composite", "svideo" }; /* ----------------------------------------------------------------------- */ -static inline int vpx3220_write(struct i2c_client *client, u8 reg, u8 value) +static inline int vpx3220_write(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); struct vpx3220 *decoder = i2c_get_clientdata(client); decoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static inline int vpx3220_read(struct i2c_client *client, u8 reg) +static inline int vpx3220_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } -static int vpx3220_fp_status(struct i2c_client *client) +static int vpx3220_fp_status(struct v4l2_subdev *sd) { unsigned char status; unsigned int i; for (i = 0; i < VPX_TIMEOUT_COUNT; i++) { - status = vpx3220_read(client, 0x29); + status = vpx3220_read(sd, 0x29); if (!(status & 4)) return 0; @@ -92,57 +105,60 @@ static int vpx3220_fp_status(struct i2c_client *client) return -1; } -static int vpx3220_fp_write(struct i2c_client *client, u8 fpaddr, u16 data) +static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + /* Write the 16-bit address to the FPWR register */ if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) { - v4l_dbg(1, debug, client, "%s: failed\n", __func__); + v4l2_dbg(1, debug, sd, "%s: failed\n", __func__); return -1; } - if (vpx3220_fp_status(client) < 0) + if (vpx3220_fp_status(sd) < 0) return -1; /* Write the 16-bit data to the FPDAT register */ if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) { - v4l_dbg(1, debug, client, "%s: failed\n", __func__); + v4l2_dbg(1, debug, sd, "%s: failed\n", __func__); return -1; } return 0; } -static u16 vpx3220_fp_read(struct i2c_client *client, u16 fpaddr) +static u16 vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr) { + struct i2c_client *client = v4l2_get_subdevdata(sd); s16 data; /* Write the 16-bit address to the FPRD register */ if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) { - v4l_dbg(1, debug, client, "%s: failed\n", __func__); + v4l2_dbg(1, debug, sd, "%s: failed\n", __func__); return -1; } - if (vpx3220_fp_status(client) < 0) + if (vpx3220_fp_status(sd) < 0) return -1; /* Read the 16-bit data from the FPDAT register */ data = i2c_smbus_read_word_data(client, 0x28); if (data == -1) { - v4l_dbg(1, debug, client, "%s: failed\n", __func__); + v4l2_dbg(1, debug, sd, "%s: failed\n", __func__); return -1; } return swab16(data); } -static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsigned int len) +static int vpx3220_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { u8 reg; int ret = -1; while (len >= 2) { reg = *data++; - ret = vpx3220_write(client, reg, *data++); + ret = vpx3220_write(sd, reg, *data++); if (ret < 0) break; len -= 2; @@ -151,7 +167,7 @@ static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsign return ret; } -static int vpx3220_write_fp_block(struct i2c_client *client, +static int vpx3220_write_fp_block(struct v4l2_subdev *sd, const u16 *data, unsigned int len) { u8 reg; @@ -159,7 +175,7 @@ static int vpx3220_write_fp_block(struct i2c_client *client, while (len > 1) { reg = *data++; - ret |= vpx3220_fp_write(client, reg, *data++); + ret |= vpx3220_fp_write(sd, reg, *data++); len -= 2; } @@ -262,294 +278,295 @@ static const unsigned short init_fp[] = { }; #if 0 -static void vpx3220_dump_i2c(struct i2c_client *client) +static void vpx3220_dump_i2c(struct v4l2_subdev *sd) { int len = sizeof(init_common); const unsigned char *data = init_common; while (len > 1) { - v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n", - *data, vpx3220_read(client, *data)); + v4l2_dbg(1, debug, sd, "i2c reg 0x%02x data 0x%02x\n", + *data, vpx3220_read(sd, *data)); data += 2; len -= 2; } } #endif -static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) +static int vpx3220_init(struct v4l2_subdev *sd, u32 val) { - struct vpx3220 *decoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: - { - vpx3220_write_block(client, init_common, - sizeof(init_common)); - vpx3220_write_fp_block(client, init_fp, - sizeof(init_fp) >> 1); - if (decoder->norm & V4L2_STD_NTSC) { - vpx3220_write_fp_block(client, init_ntsc, - sizeof(init_ntsc) >> 1); - } else if (decoder->norm & V4L2_STD_PAL) { - vpx3220_write_fp_block(client, init_pal, - sizeof(init_pal) >> 1); - } else if (decoder->norm & V4L2_STD_SECAM) { - vpx3220_write_fp_block(client, init_secam, - sizeof(init_secam) >> 1); - } else { - vpx3220_write_fp_block(client, init_pal, - sizeof(init_pal) >> 1); - } - break; - } + struct vpx3220 *decoder = to_vpx3220(sd); + + vpx3220_write_block(sd, init_common, sizeof(init_common)); + vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1); + if (decoder->norm & V4L2_STD_NTSC) + vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1); + else if (decoder->norm & V4L2_STD_PAL) + vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1); + else if (decoder->norm & V4L2_STD_SECAM) + vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1); + else + vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1); + return 0; +} - case VIDIOC_QUERYSTD: - case VIDIOC_INT_G_INPUT_STATUS: - { - int res = V4L2_IN_ST_NO_SIGNAL, status; - v4l2_std_id std = 0; +static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) +{ + int res = V4L2_IN_ST_NO_SIGNAL, status; + v4l2_std_id std = 0; - v4l_dbg(1, debug, client, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); + v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); - status = vpx3220_fp_read(client, 0x0f3); + status = vpx3220_fp_read(sd, 0x0f3); - v4l_dbg(1, debug, client, "status: 0x%04x\n", status); + v4l2_dbg(1, debug, sd, "status: 0x%04x\n", status); - if (status < 0) - return status; + if (status < 0) + return status; - if ((status & 0x20) == 0) { - res = 0; + if ((status & 0x20) == 0) { + res = 0; - switch (status & 0x18) { - case 0x00: - case 0x10: - case 0x14: - case 0x18: - std = V4L2_STD_PAL; - break; + switch (status & 0x18) { + case 0x00: + case 0x10: + case 0x14: + case 0x18: + std = V4L2_STD_PAL; + break; - case 0x08: - std = V4L2_STD_SECAM; - break; + case 0x08: + std = V4L2_STD_SECAM; + break; - case 0x04: - case 0x0c: - case 0x1c: - std = V4L2_STD_NTSC; - break; - } + case 0x04: + case 0x0c: + case 0x1c: + std = V4L2_STD_NTSC; + break; } - - if (cmd == VIDIOC_QUERYSTD) - *(v4l2_std_id *)arg = std; - else - *(int *)arg = res; - break; } + if (pstd) + *pstd = std; + if (pstatus) + *pstatus = status; + return 0; +} - case VIDIOC_S_STD: - { - v4l2_std_id *iarg = arg; - int temp_input; - - /* Here we back up the input selection because it gets - overwritten when we fill the registers with the - choosen video norm */ - temp_input = vpx3220_fp_read(client, 0xf2); - - v4l_dbg(1, debug, client, "VIDIOC_S_STD %llx\n", *iarg); - if (*iarg & V4L2_STD_NTSC) { - vpx3220_write_fp_block(client, init_ntsc, - sizeof(init_ntsc) >> 1); - v4l_dbg(1, debug, client, "norm switched to NTSC\n"); - } else if (*iarg & V4L2_STD_PAL) { - vpx3220_write_fp_block(client, init_pal, - sizeof(init_pal) >> 1); - v4l_dbg(1, debug, client, "norm switched to PAL\n"); - } else if (*iarg & V4L2_STD_SECAM) { - vpx3220_write_fp_block(client, init_secam, - sizeof(init_secam) >> 1); - v4l_dbg(1, debug, client, "norm switched to SECAM\n"); - } else { - return -EINVAL; - } +static int vpx3220_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + return vpx3220_status(sd, NULL, std); +} -#if 0 - case VIDEO_MODE_AUTO: - /* FIXME This is only preliminary support */ - data = vpx3220_fp_read(client, 0xf2) & 0x20; - vpx3220_fp_write(client, 0xf2, 0x00c0 | data); - v4l_dbg(1, debug, client, "norm switched to AUTO\n"); - break; -#endif - decoder->norm = *iarg; +static int vpx3220_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + return vpx3220_status(sd, status, NULL); +} - /* And here we set the backed up video input again */ - vpx3220_fp_write(client, 0xf2, temp_input | 0x0010); - udelay(10); - break; +static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct vpx3220 *decoder = to_vpx3220(sd); + int temp_input; + + /* Here we back up the input selection because it gets + overwritten when we fill the registers with the + choosen video norm */ + temp_input = vpx3220_fp_read(sd, 0xf2); + + v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", std); + if (std & V4L2_STD_NTSC) { + vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1); + v4l2_dbg(1, debug, sd, "norm switched to NTSC\n"); + } else if (std & V4L2_STD_PAL) { + vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1); + v4l2_dbg(1, debug, sd, "norm switched to PAL\n"); + } else if (std & V4L2_STD_SECAM) { + vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1); + v4l2_dbg(1, debug, sd, "norm switched to SECAM\n"); + } else { + return -EINVAL; } - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - int data; + decoder->norm = std; - /* RJ: *iarg = 0: ST8 (PCTV) input - *iarg = 1: COMPOSITE input - *iarg = 2: SVHS input */ + /* And here we set the backed up video input again */ + vpx3220_fp_write(sd, 0xf2, temp_input | 0x0010); + udelay(10); + return 0; +} - const int input[3][2] = { - {0x0c, 0}, - {0x0d, 0}, - {0x0e, 1} - }; +static int vpx3220_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + int data; - if (route->input < 0 || route->input > 2) - return -EINVAL; + /* RJ: route->input = 0: ST8 (PCTV) input + route->input = 1: COMPOSITE input + route->input = 2: SVHS input */ - v4l_dbg(1, debug, client, "input switched to %s\n", inputs[route->input]); + const int input[3][2] = { + {0x0c, 0}, + {0x0d, 0}, + {0x0e, 1} + }; - vpx3220_write(client, 0x33, input[route->input][0]); + if (route->input < 0 || route->input > 2) + return -EINVAL; - data = vpx3220_fp_read(client, 0xf2) & ~(0x0020); - if (data < 0) - return data; - /* 0x0010 is required to latch the setting */ - vpx3220_fp_write(client, 0xf2, - data | (input[route->input][1] << 5) | 0x0010); + v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[route->input]); - udelay(10); - break; - } + vpx3220_write(sd, 0x33, input[route->input][0]); - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - { - int on = cmd == VIDIOC_STREAMON; - v4l_dbg(1, debug, client, "VIDIOC_STREAM%s\n", on ? "ON" : "OFF"); + data = vpx3220_fp_read(sd, 0xf2) & ~(0x0020); + if (data < 0) + return data; + /* 0x0010 is required to latch the setting */ + vpx3220_fp_write(sd, 0xf2, + data | (input[route->input][1] << 5) | 0x0010); - vpx3220_write(client, 0xf2, (on ? 0x1b : 0x00)); - break; - } + udelay(10); + return 0; +} - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; +static int vpx3220_s_stream(struct v4l2_subdev *sd, int enable) +{ + v4l2_dbg(1, debug, sd, "VIDIOC_STREAM%s\n", enable ? "ON" : "OFF"); - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); - break; + vpx3220_write(sd, 0xf2, (enable ? 0x1b : 0x00)); + return 0; +} - case V4L2_CID_CONTRAST: - v4l2_ctrl_query_fill(qc, 0, 63, 1, 32); - break; +static int vpx3220_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; - case V4L2_CID_SATURATION: - v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048); - break; + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 63, 1, 32); + break; - case V4L2_CID_HUE: - v4l2_ctrl_query_fill(qc, -512, 511, 1, 0); - break; + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048); + break; - default: - return -EINVAL; - } + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, -512, 511, 1, 0); break; + + default: + return -EINVAL; } + return 0; +} - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; +static int vpx3220_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct vpx3220 *decoder = to_vpx3220(sd); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = decoder->bright; - break; - case V4L2_CID_CONTRAST: - ctrl->value = decoder->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = decoder->sat; - break; - case V4L2_CID_HUE: - ctrl->value = decoder->hue; - break; - default: - return -EINVAL; - } + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; + break; + default: + return -EINVAL; } + return 0; +} - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; +static int vpx3220_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct vpx3220 *decoder = to_vpx3220(sd); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if (decoder->bright != ctrl->value) { - decoder->bright = ctrl->value; - vpx3220_write(client, 0xe6, decoder->bright); - } - break; - case V4L2_CID_CONTRAST: - if (decoder->contrast != ctrl->value) { - /* Bit 7 and 8 is for noise shaping */ - decoder->contrast = ctrl->value; - vpx3220_write(client, 0xe7, - decoder->contrast + 192); - } - break; - case V4L2_CID_SATURATION: - if (decoder->sat != ctrl->value) { - decoder->sat = ctrl->value; - vpx3220_fp_write(client, 0xa0, decoder->sat); - } - break; - case V4L2_CID_HUE: - if (decoder->hue != ctrl->value) { - decoder->hue = ctrl->value; - vpx3220_fp_write(client, 0x1c, decoder->hue); - } - break; - default: - return -EINVAL; + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + vpx3220_write(sd, 0xe6, decoder->bright); + } + break; + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + /* Bit 7 and 8 is for noise shaping */ + decoder->contrast = ctrl->value; + vpx3220_write(sd, 0xe7, decoder->contrast + 192); + } + break; + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + vpx3220_fp_write(sd, 0xa0, decoder->sat); + } + break; + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + vpx3220_fp_write(sd, 0x1c, decoder->hue); } break; - } - default: return -EINVAL; } - return 0; } -static int vpx3220_init_client(struct i2c_client *client) +static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { - vpx3220_write_block(client, init_common, sizeof(init_common)); - vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); - /* Default to PAL */ - vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); + struct vpx3220 *decoder = to_vpx3220(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - return 0; + return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); } +static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops vpx3220_core_ops = { + .g_chip_ident = vpx3220_g_chip_ident, + .init = vpx3220_init, + .g_ctrl = vpx3220_g_ctrl, + .s_ctrl = vpx3220_s_ctrl, + .queryctrl = vpx3220_queryctrl, +}; + +static const struct v4l2_subdev_tuner_ops vpx3220_tuner_ops = { + .s_std = vpx3220_s_std, +}; + +static const struct v4l2_subdev_video_ops vpx3220_video_ops = { + .s_routing = vpx3220_s_routing, + .s_stream = vpx3220_s_stream, + .querystd = vpx3220_querystd, + .g_input_status = vpx3220_g_input_status, +}; + +static const struct v4l2_subdev_ops vpx3220_ops = { + .core = &vpx3220_core_ops, + .tuner = &vpx3220_tuner_ops, + .video = &vpx3220_video_ops, +}; + /* ----------------------------------------------------------------------- * Client management code */ -static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - static int vpx3220_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct vpx3220 *decoder; + struct v4l2_subdev *sd; const char *name = NULL; u8 ver; u16 pn; @@ -562,6 +579,8 @@ static int vpx3220_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &vpx3220_ops); decoder->norm = V4L2_STD_PAL; decoder->input = 0; decoder->enable = 1; @@ -569,11 +588,11 @@ static int vpx3220_probe(struct i2c_client *client, decoder->contrast = 32768; decoder->hue = 32768; decoder->sat = 32768; - i2c_set_clientdata(client, decoder); ver = i2c_smbus_read_byte_data(client, 0x00); pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) + i2c_smbus_read_byte_data(client, 0x01); + decoder->ident = V4L2_IDENT_VPX3220A; if (ver == 0xec) { switch (pn) { case 0x4680: @@ -581,26 +600,34 @@ static int vpx3220_probe(struct i2c_client *client, break; case 0x4260: name = "vpx3216b"; + decoder->ident = V4L2_IDENT_VPX3216B; break; case 0x4280: name = "vpx3214c"; + decoder->ident = V4L2_IDENT_VPX3214C; break; } } if (name) - v4l_info(client, "%s found @ 0x%x (%s)\n", name, + v4l2_info(sd, "%s found @ 0x%x (%s)\n", name, client->addr << 1, client->adapter->name); else - v4l_info(client, "chip (%02x:%04x) found @ 0x%x (%s)\n", + v4l2_info(sd, "chip (%02x:%04x) found @ 0x%x (%s)\n", ver, pn, client->addr << 1, client->adapter->name); - vpx3220_init_client(client); + vpx3220_write_block(sd, init_common, sizeof(init_common)); + vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1); + /* Default to PAL */ + vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1); return 0; } static int vpx3220_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_vpx3220(sd)); return 0; } -- cgit v1.2.3 From e0e60da76cfa7d502c5916f7495786e59d5e1175 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 18:47:22 +0100 Subject: adv7170: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/adv7170.c | 321 +++++++++++++++++++----------------- 1 file changed, 168 insertions(+), 153 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 323cea3a9..8c1773e46 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -34,9 +34,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include "compat.h" @@ -44,6 +44,14 @@ MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); +static unsigned short normal_i2c[] = { + 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ + 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; + static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); @@ -51,36 +59,43 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct adv7170 { + struct v4l2_subdev sd; unsigned char reg[128]; v4l2_std_id norm; int input; - int bright; - int contrast; - int hue; - int sat; }; +static inline struct adv7170 *to_adv7170(struct v4l2_subdev *sd) +{ + return container_of(sd, struct adv7170, sd); +} + static char *inputs[] = { "pass_through", "play_back" }; /* ----------------------------------------------------------------------- */ -static inline int adv7170_write(struct i2c_client *client, u8 reg, u8 value) +static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value) { - struct adv7170 *encoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct adv7170 *encoder = to_adv7170(sd); encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static inline int adv7170_read(struct i2c_client *client, u8 reg) +static inline int adv7170_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } -static int adv7170_write_block(struct i2c_client *client, +static int adv7170_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct adv7170 *encoder = to_adv7170(sd); int ret = -1; u8 reg; @@ -88,7 +103,6 @@ static int adv7170_write_block(struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct adv7170 *encoder = i2c_get_clientdata(client); u8 block_data[32]; int block_len; @@ -109,7 +123,7 @@ static int adv7170_write_block(struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - ret = adv7170_write(client, reg, *data++); + ret = adv7170_write(sd, reg, *data++); if (ret < 0) break; len -= 2; @@ -127,168 +141,165 @@ static int adv7170_write_block(struct i2c_client *client, #define TR1PLAY 0x00 static const unsigned char init_NTSC[] = { - 0x00, 0x10, // MR0 - 0x01, 0x20, // MR1 - 0x02, 0x0e, // MR2 RTC control: bits 2 and 1 - 0x03, 0x80, // MR3 - 0x04, 0x30, // MR4 - 0x05, 0x00, // Reserved - 0x06, 0x00, // Reserved - 0x07, TR0MODE, // TM0 - 0x08, TR1CAPT, // TM1 - 0x09, 0x16, // Fsc0 - 0x0a, 0x7c, // Fsc1 - 0x0b, 0xf0, // Fsc2 - 0x0c, 0x21, // Fsc3 - 0x0d, 0x00, // Subcarrier Phase - 0x0e, 0x00, // Closed Capt. Ext 0 - 0x0f, 0x00, // Closed Capt. Ext 1 - 0x10, 0x00, // Closed Capt. 0 - 0x11, 0x00, // Closed Capt. 1 - 0x12, 0x00, // Pedestal Ctl 0 - 0x13, 0x00, // Pedestal Ctl 1 - 0x14, 0x00, // Pedestal Ctl 2 - 0x15, 0x00, // Pedestal Ctl 3 - 0x16, 0x00, // CGMS_WSS_0 - 0x17, 0x00, // CGMS_WSS_1 - 0x18, 0x00, // CGMS_WSS_2 - 0x19, 0x00, // Teletext Ctl + 0x00, 0x10, /* MR0 */ + 0x01, 0x20, /* MR1 */ + 0x02, 0x0e, /* MR2 RTC control: bits 2 and 1 */ + 0x03, 0x80, /* MR3 */ + 0x04, 0x30, /* MR4 */ + 0x05, 0x00, /* Reserved */ + 0x06, 0x00, /* Reserved */ + 0x07, TR0MODE, /* TM0 */ + 0x08, TR1CAPT, /* TM1 */ + 0x09, 0x16, /* Fsc0 */ + 0x0a, 0x7c, /* Fsc1 */ + 0x0b, 0xf0, /* Fsc2 */ + 0x0c, 0x21, /* Fsc3 */ + 0x0d, 0x00, /* Subcarrier Phase */ + 0x0e, 0x00, /* Closed Capt. Ext 0 */ + 0x0f, 0x00, /* Closed Capt. Ext 1 */ + 0x10, 0x00, /* Closed Capt. 0 */ + 0x11, 0x00, /* Closed Capt. 1 */ + 0x12, 0x00, /* Pedestal Ctl 0 */ + 0x13, 0x00, /* Pedestal Ctl 1 */ + 0x14, 0x00, /* Pedestal Ctl 2 */ + 0x15, 0x00, /* Pedestal Ctl 3 */ + 0x16, 0x00, /* CGMS_WSS_0 */ + 0x17, 0x00, /* CGMS_WSS_1 */ + 0x18, 0x00, /* CGMS_WSS_2 */ + 0x19, 0x00, /* Teletext Ctl */ }; static const unsigned char init_PAL[] = { - 0x00, 0x71, // MR0 - 0x01, 0x20, // MR1 - 0x02, 0x0e, // MR2 RTC control: bits 2 and 1 - 0x03, 0x80, // MR3 - 0x04, 0x30, // MR4 - 0x05, 0x00, // Reserved - 0x06, 0x00, // Reserved - 0x07, TR0MODE, // TM0 - 0x08, TR1CAPT, // TM1 - 0x09, 0xcb, // Fsc0 - 0x0a, 0x8a, // Fsc1 - 0x0b, 0x09, // Fsc2 - 0x0c, 0x2a, // Fsc3 - 0x0d, 0x00, // Subcarrier Phase - 0x0e, 0x00, // Closed Capt. Ext 0 - 0x0f, 0x00, // Closed Capt. Ext 1 - 0x10, 0x00, // Closed Capt. 0 - 0x11, 0x00, // Closed Capt. 1 - 0x12, 0x00, // Pedestal Ctl 0 - 0x13, 0x00, // Pedestal Ctl 1 - 0x14, 0x00, // Pedestal Ctl 2 - 0x15, 0x00, // Pedestal Ctl 3 - 0x16, 0x00, // CGMS_WSS_0 - 0x17, 0x00, // CGMS_WSS_1 - 0x18, 0x00, // CGMS_WSS_2 - 0x19, 0x00, // Teletext Ctl + 0x00, 0x71, /* MR0 */ + 0x01, 0x20, /* MR1 */ + 0x02, 0x0e, /* MR2 RTC control: bits 2 and 1 */ + 0x03, 0x80, /* MR3 */ + 0x04, 0x30, /* MR4 */ + 0x05, 0x00, /* Reserved */ + 0x06, 0x00, /* Reserved */ + 0x07, TR0MODE, /* TM0 */ + 0x08, TR1CAPT, /* TM1 */ + 0x09, 0xcb, /* Fsc0 */ + 0x0a, 0x8a, /* Fsc1 */ + 0x0b, 0x09, /* Fsc2 */ + 0x0c, 0x2a, /* Fsc3 */ + 0x0d, 0x00, /* Subcarrier Phase */ + 0x0e, 0x00, /* Closed Capt. Ext 0 */ + 0x0f, 0x00, /* Closed Capt. Ext 1 */ + 0x10, 0x00, /* Closed Capt. 0 */ + 0x11, 0x00, /* Closed Capt. 1 */ + 0x12, 0x00, /* Pedestal Ctl 0 */ + 0x13, 0x00, /* Pedestal Ctl 1 */ + 0x14, 0x00, /* Pedestal Ctl 2 */ + 0x15, 0x00, /* Pedestal Ctl 3 */ + 0x16, 0x00, /* CGMS_WSS_0 */ + 0x17, 0x00, /* CGMS_WSS_1 */ + 0x18, 0x00, /* CGMS_WSS_2 */ + 0x19, 0x00, /* Teletext Ctl */ }; -static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) +static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - struct adv7170 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: -#if 0 /* keep */ - /* This is just for testing!!! */ - adv7170_write_block(client, init_common, - sizeof(init_common)); - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); -#endif - break; - - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id iarg = *(v4l2_std_id *) arg; - - v4l_dbg(1, debug, client, "set norm %llx\n", iarg); - - if (iarg & V4L2_STD_NTSC) { - adv7170_write_block(client, init_NTSC, - sizeof(init_NTSC)); - if (encoder->input == 0) - adv7170_write(client, 0x02, 0x0e); // Enable genlock - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); - } else if (iarg & V4L2_STD_PAL) { - adv7170_write_block(client, init_PAL, - sizeof(init_PAL)); - if (encoder->input == 0) - adv7170_write(client, 0x02, 0x0e); // Enable genlock - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); - } else { - v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %llx\n", iarg); - encoder->norm = iarg; - break; + struct adv7170 *encoder = to_adv7170(sd); + + v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + + if (std & V4L2_STD_NTSC) { + adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC)); + if (encoder->input == 0) + adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */ + adv7170_write(sd, 0x07, TR0MODE | TR0RST); + adv7170_write(sd, 0x07, TR0MODE); + } else if (std & V4L2_STD_PAL) { + adv7170_write_block(sd, init_PAL, sizeof(init_PAL)); + if (encoder->input == 0) + adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */ + adv7170_write(sd, 0x07, TR0MODE | TR0RST); + adv7170_write(sd, 0x07, TR0MODE); + } else { + v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std); + return -EINVAL; } + v4l2_dbg(1, debug, sd, "switched to %llx\n", std); + encoder->norm = std; + return 0; +} - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; +static int adv7170_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct adv7170 *encoder = to_adv7170(sd); - /* RJ: *iarg = 0: input is from decoder - *iarg = 1: input is from ZR36060 - *iarg = 2: color bar */ + /* RJ: route->input = 0: input is from decoder + route->input = 1: input is from ZR36060 + route->input = 2: color bar */ - v4l_dbg(1, debug, client, "set input from %s\n", + v4l2_dbg(1, debug, sd, "set input from %s\n", route->input == 0 ? "decoder" : "ZR36060"); - switch (route->input) { - case 0: - adv7170_write(client, 0x01, 0x20); - adv7170_write(client, 0x08, TR1CAPT); /* TR1 */ - adv7170_write(client, 0x02, 0x0e); // Enable genlock - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); - /* udelay(10); */ - break; - - case 1: - adv7170_write(client, 0x01, 0x00); - adv7170_write(client, 0x08, TR1PLAY); /* TR1 */ - adv7170_write(client, 0x02, 0x08); - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); - /* udelay(10); */ - break; - - default: - v4l_dbg(1, debug, client, "illegal input: %d\n", route->input); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]); - encoder->input = route->input; + switch (route->input) { + case 0: + adv7170_write(sd, 0x01, 0x20); + adv7170_write(sd, 0x08, TR1CAPT); /* TR1 */ + adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */ + adv7170_write(sd, 0x07, TR0MODE | TR0RST); + adv7170_write(sd, 0x07, TR0MODE); + /* udelay(10); */ + break; + + case 1: + adv7170_write(sd, 0x01, 0x00); + adv7170_write(sd, 0x08, TR1PLAY); /* TR1 */ + adv7170_write(sd, 0x02, 0x08); + adv7170_write(sd, 0x07, TR0MODE | TR0RST); + adv7170_write(sd, 0x07, TR0MODE); + /* udelay(10); */ break; - } default: + v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input); return -EINVAL; } - + v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]); + encoder->input = route->input; return 0; } +static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); +} + +static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static unsigned short normal_i2c[] = { - 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ - 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ - I2C_CLIENT_END +static const struct v4l2_subdev_core_ops adv7170_core_ops = { + .g_chip_ident = adv7170_g_chip_ident, }; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops adv7170_video_ops = { + .s_std_output = adv7170_s_std_output, + .s_routing = adv7170_s_routing, +}; + +static const struct v4l2_subdev_ops adv7170_ops = { + .core = &adv7170_core_ops, + .video = &adv7170_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int adv7170_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct adv7170 *encoder; + struct v4l2_subdev *sd; int i; /* Check if the adapter supports the needed features */ @@ -301,25 +312,29 @@ static int adv7170_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &adv7170_ops); encoder->norm = V4L2_STD_NTSC; encoder->input = 0; - i2c_set_clientdata(client, encoder); - i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); + i = adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC)); if (i >= 0) { - i = adv7170_write(client, 0x07, TR0MODE | TR0RST); - i = adv7170_write(client, 0x07, TR0MODE); - i = adv7170_read(client, 0x12); - v4l_dbg(1, debug, client, "revision %d\n", i & 1); + i = adv7170_write(sd, 0x07, TR0MODE | TR0RST); + i = adv7170_write(sd, 0x07, TR0MODE); + i = adv7170_read(sd, 0x12); + v4l2_dbg(1, debug, sd, "revision %d\n", i & 1); } if (i < 0) - v4l_dbg(1, debug, client, "init error 0x%x\n", i); + v4l2_dbg(1, debug, sd, "init error 0x%x\n", i); return 0; } static int adv7170_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_adv7170(sd)); return 0; } -- cgit v1.2.3 From 5035f8b26e88356d9ec7ed34b895edcb45c89cfb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 18:56:37 +0100 Subject: adv7175: convert to v4l2-subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/adv7170.c | 2 +- linux/drivers/media/video/adv7175.c | 307 +++++++++++++++++++----------------- 2 files changed, 166 insertions(+), 143 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 8c1773e46..6dd63d36c 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -269,7 +269,7 @@ static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide { struct i2c_client *client = v4l2_get_subdevdata(sd); - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7170, 0); } static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c index 11c92440e..61ab7b165 100644 --- a/linux/drivers/media/video/adv7175.c +++ b/linux/drivers/media/video/adv7175.c @@ -30,9 +30,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include "compat.h" @@ -40,6 +40,17 @@ MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); +#define I2C_ADV7175 0xd4 +#define I2C_ADV7176 0x54 + +static unsigned short normal_i2c[] = { + I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, + I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; + static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); @@ -47,34 +58,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct adv7175 { + struct v4l2_subdev sd; v4l2_std_id norm; int input; - int bright; - int contrast; - int hue; - int sat; }; -#define I2C_ADV7175 0xd4 -#define I2C_ADV7176 0x54 +static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd) +{ + return container_of(sd, struct adv7175, sd); +} static char *inputs[] = { "pass_through", "play_back", "color_bar" }; /* ----------------------------------------------------------------------- */ -static inline int adv7175_write(struct i2c_client *client, u8 reg, u8 value) +static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_write_byte_data(client, reg, value); } -static inline int adv7175_read(struct i2c_client *client, u8 reg) +static inline int adv7175_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } -static int adv7175_write_block(struct i2c_client *client, +static int adv7175_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = -1; u8 reg; @@ -102,7 +117,7 @@ static int adv7175_write_block(struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - ret = adv7175_write(client, reg, *data++); + ret = adv7175_write(sd, reg, *data++); if (ret < 0) break; len -= 2; @@ -112,18 +127,18 @@ static int adv7175_write_block(struct i2c_client *client, return ret; } -static void set_subcarrier_freq(struct i2c_client *client, int pass_through) +static void set_subcarrier_freq(struct v4l2_subdev *sd, int pass_through) { /* for some reason pass_through NTSC needs * a different sub-carrier freq to remain stable. */ if (pass_through) - adv7175_write(client, 0x02, 0x00); + adv7175_write(sd, 0x02, 0x00); else - adv7175_write(client, 0x02, 0x55); + adv7175_write(sd, 0x02, 0x55); - adv7175_write(client, 0x03, 0x55); - adv7175_write(client, 0x04, 0x55); - adv7175_write(client, 0x05, 0x25); + adv7175_write(sd, 0x03, 0x55); + adv7175_write(sd, 0x04, 0x55); + adv7175_write(sd, 0x05, 0x25); } /* ----------------------------------------------------------------------- */ @@ -183,144 +198,148 @@ static const unsigned char init_ntsc[] = { 0x06, 0x1a, /* subc. phase */ }; -static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) +static int adv7175_init(struct v4l2_subdev *sd, u32 val) +{ + /* This is just for testing!!! */ + adv7175_write_block(sd, init_common, sizeof(init_common)); + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + return 0; +} + +static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - struct adv7175 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: - /* This is just for testing!!! */ - adv7175_write_block(client, init_common, - sizeof(init_common)); - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); + struct adv7175 *encoder = to_adv7175(sd); + + if (std & V4L2_STD_NTSC) { + adv7175_write_block(sd, init_ntsc, sizeof(init_ntsc)); + if (encoder->input == 0) + adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + } else if (std & V4L2_STD_PAL) { + adv7175_write_block(sd, init_pal, sizeof(init_pal)); + if (encoder->input == 0) + adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + } else if (std & V4L2_STD_SECAM) { + /* This is an attempt to convert + * SECAM->PAL (typically it does not work + * due to genlock: when decoder is in SECAM + * and encoder in in PAL the subcarrier can + * not be syncronized with horizontal + * quency) */ + adv7175_write_block(sd, init_pal, sizeof(init_pal)); + if (encoder->input == 0) + adv7175_write(sd, 0x0d, 0x49); /* Disable genlock */ + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + } else { + v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std); + return -EINVAL; + } + v4l2_dbg(1, debug, sd, "switched to %llx\n", std); + encoder->norm = std; + return 0; +} + +static int adv7175_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct adv7175 *encoder = to_adv7175(sd); + + /* RJ: route->input = 0: input is from decoder + route->input = 1: input is from ZR36060 + route->input = 2: color bar */ + + switch (route->input) { + case 0: + adv7175_write(sd, 0x01, 0x00); + + if (encoder->norm & V4L2_STD_NTSC) + set_subcarrier_freq(sd, 1); + + adv7175_write(sd, 0x0c, TR1CAPT); /* TR1 */ + if (encoder->norm & V4L2_STD_SECAM) + adv7175_write(sd, 0x0d, 0x49); /* Disable genlock */ + else + adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + /*udelay(10);*/ break; - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id iarg = *(v4l2_std_id *) arg; - - if (iarg & V4L2_STD_NTSC) { - adv7175_write_block(client, init_ntsc, - sizeof(init_ntsc)); - if (encoder->input == 0) - adv7175_write(client, 0x0d, 0x4f); // Enable genlock - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - } else if (iarg & V4L2_STD_PAL) { - adv7175_write_block(client, init_pal, - sizeof(init_pal)); - if (encoder->input == 0) - adv7175_write(client, 0x0d, 0x4f); // Enable genlock - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - } else if (iarg & V4L2_STD_SECAM) { - /* This is an attempt to convert - * SECAM->PAL (typically it does not work - * due to genlock: when decoder is in SECAM - * and encoder in in PAL the subcarrier can - * not be syncronized with horizontal - * quency) */ - adv7175_write_block(client, init_pal, - sizeof(init_pal)); - if (encoder->input == 0) - adv7175_write(client, 0x0d, 0x49); // Disable genlock - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - } else { - v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %llx\n", iarg); - encoder->norm = iarg; + case 1: + adv7175_write(sd, 0x01, 0x00); + + if (encoder->norm & V4L2_STD_NTSC) + set_subcarrier_freq(sd, 0); + + adv7175_write(sd, 0x0c, TR1PLAY); /* TR1 */ + adv7175_write(sd, 0x0d, 0x49); + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + /* udelay(10); */ break; - } - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - /* RJ: *iarg = 0: input is from SAA7110 - *iarg = 1: input is from ZR36060 - *iarg = 2: color bar */ - - switch (route->input) { - case 0: - adv7175_write(client, 0x01, 0x00); - - if (encoder->norm & V4L2_STD_NTSC) - set_subcarrier_freq(client, 1); - - adv7175_write(client, 0x0c, TR1CAPT); /* TR1 */ - if (encoder->norm & V4L2_STD_SECAM) - adv7175_write(client, 0x0d, 0x49); // Disable genlock - else - adv7175_write(client, 0x0d, 0x4f); // Enable genlock - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - //udelay(10); - break; - - case 1: - adv7175_write(client, 0x01, 0x00); - - if (encoder->norm & V4L2_STD_NTSC) - set_subcarrier_freq(client, 0); - - adv7175_write(client, 0x0c, TR1PLAY); /* TR1 */ - adv7175_write(client, 0x0d, 0x49); - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - /* udelay(10); */ - break; - - case 2: - adv7175_write(client, 0x01, 0x80); - - if (encoder->norm & V4L2_STD_NTSC) - set_subcarrier_freq(client, 0); - - adv7175_write(client, 0x0d, 0x49); - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - /* udelay(10); */ - break; - - default: - v4l_dbg(1, debug, client, "illegal input: %d\n", route->input); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]); - encoder->input = route->input; + case 2: + adv7175_write(sd, 0x01, 0x80); + + if (encoder->norm & V4L2_STD_NTSC) + set_subcarrier_freq(sd, 0); + + adv7175_write(sd, 0x0d, 0x49); + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + /* udelay(10); */ break; - } default: + v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input); return -EINVAL; } - + v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]); + encoder->input = route->input; return 0; } +static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0); +} + +static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = { - I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, - I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, - I2C_CLIENT_END +static const struct v4l2_subdev_core_ops adv7175_core_ops = { + .g_chip_ident = adv7175_g_chip_ident, + .init = adv7175_init, }; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops adv7175_video_ops = { + .s_std_output = adv7175_s_std_output, + .s_routing = adv7175_s_routing, +}; + +static const struct v4l2_subdev_ops adv7175_ops = { + .core = &adv7175_core_ops, + .video = &adv7175_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int adv7175_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i; struct adv7175 *encoder; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -332,25 +351,29 @@ static int adv7175_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &adv7175_ops); encoder->norm = V4L2_STD_NTSC; encoder->input = 0; - i2c_set_clientdata(client, encoder); - i = adv7175_write_block(client, init_common, sizeof(init_common)); + i = adv7175_write_block(sd, init_common, sizeof(init_common)); if (i >= 0) { - i = adv7175_write(client, 0x07, TR0MODE | TR0RST); - i = adv7175_write(client, 0x07, TR0MODE); - i = adv7175_read(client, 0x12); - v4l_dbg(1, debug, client, "revision %d\n", i & 1); + i = adv7175_write(sd, 0x07, TR0MODE | TR0RST); + i = adv7175_write(sd, 0x07, TR0MODE); + i = adv7175_read(sd, 0x12); + v4l2_dbg(1, debug, sd, "revision %d\n", i & 1); } if (i < 0) - v4l_dbg(1, debug, client, "init error 0x%x\n", i); + v4l2_dbg(1, debug, sd, "init error 0x%x\n", i); return 0; } static int adv7175_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_adv7175(sd)); return 0; } -- cgit v1.2.3 From e9e48721ed72a07c7d841000bfaeda024af28217 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Feb 2009 19:34:48 +0100 Subject: gspca - sonixj: Handle the webcam 0c45:613c instead of sn9c102. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 2 +- linux/drivers/media/video/sn9c102/sn9c102_devtable.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 5cdb643b8..36d6f50be 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -2199,9 +2199,9 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)}, +#endif {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */ -#endif {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, {} }; diff --git a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h index 8cb3457e7..41dfb60f4 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -123,7 +123,9 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, +#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, { } }; -- cgit v1.2.3 From 36c7a4cef04513ddb801f8b65ce0b8fcc0228d87 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Feb 2009 19:38:31 +0100 Subject: gspca - zc3xx: Bad probe of the ov7xxx sensors. From: Jean-Francois Moine This patch fixes one bug of the kernel bug report 12737. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/zc3xx.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index b93573f66..c885146cc 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -7016,7 +7016,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) static int zcxx_probeSensor(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int sensor, sensor2; + int sensor; switch (sd->sensor) { case SENSOR_MC501CB: @@ -7031,16 +7031,9 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev) break; } sensor = vga_2wr_probe(gspca_dev); - if (sensor >= 0) { - if (sensor < 0x7600) - return sensor; - /* next probe is needed for OmniVision ? */ - } - sensor2 = vga_3wr_probe(gspca_dev); - if (sensor2 >= 0 - && sensor >= 0) + if (sensor >= 0) return sensor; - return sensor2; + return vga_3wr_probe(gspca_dev); } /* this function is called at probe time */ -- cgit v1.2.3 From 34a37624e9b1eb3c2c938700af69d147ee3e6a7d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Feb 2009 19:41:28 +0100 Subject: gspca - zc3xx: Bad probe of the ov7630c sensor. From: Jean-Francois Moine This patch fixes an other bug of the kernel bug report 12737. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/zc3xx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index c885146cc..ad385b9a0 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -7170,6 +7170,10 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_PROBE, "Find Sensor OV7620"); sd->sensor = SENSOR_OV7620; break; + case 0x7631: + PDEBUG(D_PROBE, "Find Sensor OV7630C"); + sd->sensor = SENSOR_OV7630C; + break; case 0x7648: PDEBUG(D_PROBE, "Find Sensor OV7648"); sd->sensor = SENSOR_OV7620; /* same sensor (?) */ -- cgit v1.2.3 From 2bc35f692273756abf6b34a349e43a47bd9b8e14 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 20:18:23 +0100 Subject: zoran: convert to v4l2_device/v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran.h | 19 +- linux/drivers/media/video/zoran/zoran_card.c | 263 ++++++++----------------- linux/drivers/media/video/zoran/zoran_device.c | 74 +++---- linux/drivers/media/video/zoran/zoran_device.h | 13 +- linux/drivers/media/video/zoran/zoran_driver.c | 78 ++------ 5 files changed, 159 insertions(+), 288 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran.h b/linux/drivers/media/video/zoran/zoran.h index a323eb66e..ab1ced262 100644 --- a/linux/drivers/media/video/zoran/zoran.h +++ b/linux/drivers/media/video/zoran/zoran.h @@ -31,6 +31,8 @@ #ifndef _BUZ_H_ #define _BUZ_H_ +#include + struct zoran_requestbuffers { unsigned long count; /* Number of buffers for MJPEG grabbing */ unsigned long size; /* Size PER BUFFER in bytes */ @@ -339,7 +341,12 @@ struct zoran_fh { struct card_info { enum card_type type; char name[32]; - u16 i2c_decoder, i2c_encoder; /* I2C types */ + const char *i2c_decoder; /* i2c decoder device */ + const char *mod_decoder; /* i2c decoder module */ + const unsigned short *addrs_decoder; + const char *i2c_encoder; /* i2c encoder device */ + const char *mod_encoder; /* i2c encoder module */ + const unsigned short *addrs_encoder; u16 video_vfe, video_codec; /* videocodec types */ u16 audio_chip; /* audio type */ @@ -370,14 +377,15 @@ struct card_info { }; struct zoran { + struct v4l2_device v4l2_dev; struct video_device *video_dev; struct i2c_adapter i2c_adapter; /* */ struct i2c_algo_bit_data i2c_algo; /* */ u32 i2cbr; - struct i2c_client *decoder; /* video decoder i2c client */ - struct i2c_client *encoder; /* video encoder i2c client */ + struct v4l2_subdev *decoder; /* video decoder sub-device */ + struct v4l2_subdev *encoder; /* video encoder sub-device */ struct videocodec *codec; /* video codec */ struct videocodec *vfe; /* video front end */ @@ -481,6 +489,11 @@ struct zoran { wait_queue_head_t test_q; }; +static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct zoran, v4l2_dev); +} + /* There was something called _ALPHA_BUZ that used the PCI address instead of * the kernel iomapped address for btread/btwrite. */ #define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr)) diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 37f75045f..f60fba83a 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -332,47 +332,6 @@ avs6eyes_init (struct zoran *zr) } -static char * -i2cid_to_modulename (u16 i2c_id) -{ - char *name = NULL; - - switch (i2c_id) { - case I2C_DRIVERID_SAA7110: - name = "saa7110"; - break; - case I2C_DRIVERID_SAA711X: - name = "saa7115"; - break; - case I2C_DRIVERID_SAA7185B: - name = "saa7185"; - break; - case I2C_DRIVERID_ADV7170: - name = "adv7170"; - break; - case I2C_DRIVERID_ADV7175: - name = "adv7175"; - break; - case I2C_DRIVERID_BT819: - name = "bt819"; - break; - case I2C_DRIVERID_BT856: - name = "bt856"; - break; - case I2C_DRIVERID_BT866: - name = "bt866"; - break; - case I2C_DRIVERID_VPX3220: - name = "vpx3220"; - break; - case I2C_DRIVERID_KS0127: - name = "ks0127"; - break; - } - - return name; -} - static char * codecid_to_modulename (u16 codecid) { @@ -423,11 +382,24 @@ static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 } static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 }; static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 }; +static const unsigned short vpx3220_addrs[] = { 0x43, 0x47, I2C_CLIENT_END }; +static const unsigned short saa7110_addrs[] = { 0x4e, 0x4f, I2C_CLIENT_END }; +static const unsigned short saa7111_addrs[] = { 0x25, 0x24, I2C_CLIENT_END }; +static const unsigned short saa7114_addrs[] = { 0x21, 0x20, I2C_CLIENT_END }; +static const unsigned short adv717x_addrs[] = { 0x6a, 0x6b, 0x2a, 0x2b, I2C_CLIENT_END }; +static const unsigned short ks0127_addrs[] = { 0x6c, 0x6d, I2C_CLIENT_END }; +static const unsigned short saa7185_addrs[] = { 0x44, I2C_CLIENT_END }; +static const unsigned short bt819_addrs[] = { 0x45, I2C_CLIENT_END }; +static const unsigned short bt856_addrs[] = { 0x44, I2C_CLIENT_END }; +static const unsigned short bt866_addrs[] = { 0x44, I2C_CLIENT_END }; + static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { .type = DC10_old, .name = "DC10(old)", - .i2c_decoder = I2C_DRIVERID_VPX3220, + .i2c_decoder = "vpx3220a", + .mod_decoder = "vpx3220", + .addrs_decoder = vpx3220_addrs, .video_codec = CODEC_TYPE_ZR36050, .video_vfe = CODEC_TYPE_ZR36016, @@ -455,8 +427,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC10_new, .name = "DC10(new)", - .i2c_decoder = I2C_DRIVERID_SAA7110, - .i2c_encoder = I2C_DRIVERID_ADV7175, + .i2c_decoder = "saa7110", + .mod_decoder = "saa7110", + .addrs_decoder = saa7110_addrs, + .i2c_encoder = "adv7175", + .mod_encoder = "adv7175", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 3, @@ -482,8 +458,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC10plus, .name = "DC10plus", - .i2c_decoder = I2C_DRIVERID_SAA7110, - .i2c_encoder = I2C_DRIVERID_ADV7175, + .i2c_decoder = "saa7110", + .mod_decoder = "saa7110", + .addrs_decoder = saa7110_addrs, + .i2c_encoder = "adv7175", + .mod_encoder = "adv7175", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 3, @@ -510,8 +490,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC30, .name = "DC30", - .i2c_decoder = I2C_DRIVERID_VPX3220, - .i2c_encoder = I2C_DRIVERID_ADV7175, + .i2c_decoder = "vpx3220a", + .mod_decoder = "vpx3220", + .addrs_decoder = vpx3220_addrs, + .i2c_encoder = "adv7175", + .mod_encoder = "adv7175", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36050, .video_vfe = CODEC_TYPE_ZR36016, @@ -539,8 +523,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC30plus, .name = "DC30plus", - .i2c_decoder = I2C_DRIVERID_VPX3220, - .i2c_encoder = I2C_DRIVERID_ADV7175, + .i2c_decoder = "vpx3220a", + .mod_decoder = "vpx3220", + .addrs_decoder = vpx3220_addrs, + .i2c_encoder = "adv7175", + .mod_encoder = "adv7175", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36050, .video_vfe = CODEC_TYPE_ZR36016, @@ -568,8 +556,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = LML33, .name = "LML33", - .i2c_decoder = I2C_DRIVERID_BT819, - .i2c_encoder = I2C_DRIVERID_BT856, + .i2c_decoder = "bt819a", + .mod_decoder = "bt819", + .addrs_decoder = bt819_addrs, + .i2c_encoder = "bt856", + .mod_encoder = "bt856", + .addrs_encoder = bt856_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 2, @@ -595,8 +587,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = LML33R10, .name = "LML33R10", - .i2c_decoder = I2C_DRIVERID_SAA711X, - .i2c_encoder = I2C_DRIVERID_ADV7170, + .i2c_decoder = "saa7114", + .mod_decoder = "saa7115", + .addrs_decoder = saa7114_addrs, + .i2c_encoder = "adv7170", + .mod_encoder = "adv7170", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 2, @@ -622,8 +618,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = BUZ, .name = "Buz", - .i2c_decoder = I2C_DRIVERID_SAA711X, - .i2c_encoder = I2C_DRIVERID_SAA7185B, + .i2c_decoder = "saa7111", + .mod_decoder = "saa7115", + .addrs_decoder = saa7111_addrs, + .i2c_encoder = "saa7185", + .mod_encoder = "saa7185", + .addrs_encoder = saa7185_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 2, @@ -651,8 +651,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { .name = "6-Eyes", /* AverMedia chose not to brand the 6-Eyes. Thus it can't be autodetected, and requires card=x. */ - .i2c_decoder = I2C_DRIVERID_KS0127, - .i2c_encoder = I2C_DRIVERID_BT866, + .i2c_decoder = "ks0127", + .mod_decoder = "ks0127", + .addrs_decoder = ks0127_addrs, + .i2c_encoder = "bt866", + .mod_encoder = "bt866", + .addrs_encoder = bt866_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 10, @@ -733,69 +737,6 @@ zoran_i2c_setscl (void *data, btwrite(zr->i2cbr, ZR36057_I2CBR); } -static int -zoran_i2c_client_register (struct i2c_client *client) -{ - struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter); - int res = 0; - - dprintk(2, - KERN_DEBUG "%s: i2c_client_register() - driver id = %d\n", - ZR_DEVNAME(zr), client->driver->id); - - mutex_lock(&zr->resource_lock); - - if (zr->user > 0) { - /* we're already busy, so we keep a reference to - * them... Could do a lot of stuff here, but this - * is easiest. (Did I ever mention I'm a lazy ass?) - */ - res = -EBUSY; - goto clientreg_unlock_and_return; - } - - if (client->driver->id == zr->card.i2c_decoder) - zr->decoder = client; - else if (client->driver->id == zr->card.i2c_encoder) - zr->encoder = client; - else { - res = -ENODEV; - goto clientreg_unlock_and_return; - } - -clientreg_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; -} - -static int -zoran_i2c_client_unregister (struct i2c_client *client) -{ - struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter); - int res = 0; - - dprintk(2, KERN_DEBUG "%s: i2c_client_unregister()\n", ZR_DEVNAME(zr)); - - mutex_lock(&zr->resource_lock); - - if (zr->user > 0) { - res = -EBUSY; - goto clientunreg_unlock_and_return; - } - - /* try to locate it */ - if (client == zr->encoder) { - zr->encoder = NULL; - } else if (client == zr->decoder) { - zr->decoder = NULL; - snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%d]", zr->id); - } -clientunreg_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; -} - static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = { .setsda = zoran_i2c_setsda, .setscl = zoran_i2c_setscl, @@ -811,13 +752,10 @@ zoran_register_i2c (struct zoran *zr) memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template, sizeof(struct i2c_algo_bit_data)); zr->i2c_algo.data = zr; - zr->i2c_adapter.class = I2C_CLASS_TV_ANALOG; zr->i2c_adapter.id = I2C_HW_B_ZR36067; - zr->i2c_adapter.client_register = zoran_i2c_client_register; - zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister; strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr), sizeof(zr->i2c_adapter.name)); - i2c_set_adapdata(&zr->i2c_adapter, zr); + i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev); zr->i2c_adapter.algo_data = &zr->i2c_algo; zr->i2c_adapter.dev.parent = &zr->pci_dev->dev; return i2c_bit_add_bus(&zr->i2c_adapter); @@ -1174,8 +1112,8 @@ zr36057_init (struct zoran *zr) if (!pass_through) { struct v4l2_routing route = { 2, 0 }; - decoder_command(zr, VIDIOC_STREAMOFF, 0); - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_call(zr, video, s_stream, 0); + encoder_call(zr, video, s_routing, &route); } zr->zoran_proc = NULL; @@ -1190,7 +1128,8 @@ exit_free: static void __devexit zoran_remove(struct pci_dev *pdev) { - struct zoran *zr = pci_get_drvdata(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct zoran *zr = to_zoran(v4l2_dev); if (!zr->initialized) goto exit_free; @@ -1223,7 +1162,7 @@ static void __devexit zoran_remove(struct pci_dev *pdev) pci_disable_device(zr->pci_dev); video_unregister_device(zr->video_dev); exit_free: - pci_set_drvdata(pdev, NULL); + v4l2_device_unregister(&zr->v4l2_dev); kfree(zr); } @@ -1295,7 +1234,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, struct videocodec_master *master_vfe = NULL; struct videocodec_master *master_codec = NULL; int card_num; - char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name; + char *codec_name, *vfe_name; unsigned int nr; @@ -1316,13 +1255,15 @@ static int __devinit zoran_probe(struct pci_dev *pdev, ZORAN_NAME); return -ENOMEM; } + if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev)) + goto zr_free_mem; zr->pci_dev = pdev; zr->id = nr; snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); spin_lock_init(&zr->spinlock); mutex_init(&zr->resource_lock); if (pci_enable_device(pdev)) - goto zr_free_mem; + goto zr_unreg; pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); dprintk(1, @@ -1349,7 +1290,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, KERN_ERR "%s: It is not possible to auto-detect ZR36057 based cards\n", ZR_DEVNAME(zr)); - goto zr_free_mem; + goto zr_unreg; } card_num = ent->driver_data; @@ -1358,7 +1299,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, KERN_ERR "%s: Unknown card, try specifying card=X module parameter\n", ZR_DEVNAME(zr)); - goto zr_free_mem; + goto zr_unreg; } dprintk(3, KERN_DEBUG @@ -1371,7 +1312,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, KERN_ERR "%s: User specified card type %d out of range (0 .. %d)\n", ZR_DEVNAME(zr), card_num, NUM_CARDS - 1); - goto zr_free_mem; + goto zr_unreg; } } @@ -1390,7 +1331,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, KERN_ERR "%s: %s() - ioremap failed\n", ZR_DEVNAME(zr), __func__); - goto zr_free_mem; + goto zr_unreg; } result = request_irq(zr->pci_dev->irq, zoran_irq, @@ -1433,46 +1374,6 @@ static int __devinit zoran_probe(struct pci_dev *pdev, dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n", ZR_DEVNAME(zr)); - /* i2c decoder */ - if (decoder[zr->id] != -1) { - i2c_dec_name = i2cid_to_modulename(decoder[zr->id]); - zr->card.i2c_decoder = decoder[zr->id]; - } else if (zr->card.i2c_decoder != 0) { - i2c_dec_name = i2cid_to_modulename(zr->card.i2c_decoder); - } else { - i2c_dec_name = NULL; - } - - if (i2c_dec_name) { - result = request_module(i2c_dec_name); - if (result < 0) { - dprintk(1, - KERN_ERR - "%s: failed to load module %s: %d\n", - ZR_DEVNAME(zr), i2c_dec_name, result); - } - } - - /* i2c encoder */ - if (encoder[zr->id] != -1) { - i2c_enc_name = i2cid_to_modulename(encoder[zr->id]); - zr->card.i2c_encoder = encoder[zr->id]; - } else if (zr->card.i2c_encoder != 0) { - i2c_enc_name = i2cid_to_modulename(zr->card.i2c_encoder); - } else { - i2c_enc_name = NULL; - } - - if (i2c_enc_name) { - result = request_module(i2c_enc_name); - if (result < 0) { - dprintk(1, - KERN_ERR - "%s: failed to load module %s: %d\n", - ZR_DEVNAME(zr), i2c_enc_name, result); - } - } - if (zoran_register_i2c(zr) < 0) { dprintk(1, KERN_ERR @@ -1481,6 +1382,14 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_free_irq; } + zr->decoder = v4l2_i2c_new_probed_subdev(&zr->i2c_adapter, + zr->card.mod_decoder, zr->card.i2c_decoder, zr->card.addrs_decoder); + + if (zr->card.mod_encoder) + zr->encoder = v4l2_i2c_new_probed_subdev(&zr->i2c_adapter, + zr->card.mod_encoder, zr->card.i2c_encoder, + zr->card.addrs_encoder); + dprintk(2, KERN_INFO "%s: Initializing videocodec bus...\n", ZR_DEVNAME(zr)); @@ -1570,8 +1479,6 @@ static int __devinit zoran_probe(struct pci_dev *pdev, zoran_proc_init(zr); - pci_set_drvdata(pdev, zr); - return 0; zr_detach_vfe: @@ -1589,6 +1496,8 @@ zr_free_irq: free_irq(zr->pci_dev->irq, zr); zr_unmap: iounmap(zr->zr36057_mem); +zr_unreg: + v4l2_device_unregister(&zr->v4l2_dev); zr_free_mem: kfree(zr); diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index 8544c9b99..fc1be816d 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -37,15 +37,12 @@ #include #include #include "compat.h" -#include #include #include #include #include #include -#include -#include #include #include @@ -1001,9 +998,9 @@ zr36057_enable_jpg (struct zoran *zr, * the video bus direction set to input. */ set_videobus_dir(zr, 0); - decoder_command(zr, VIDIOC_STREAMON, 0); + decoder_call(zr, video, s_stream, 1); route.input = 0; - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + encoder_call(zr, video, s_routing, &route); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1049,10 +1046,10 @@ zr36057_enable_jpg (struct zoran *zr, /* In motion decompression mode, the decoder output must be disabled, and * the video bus direction set to output. */ - decoder_command(zr, VIDIOC_STREAMOFF, 0); + decoder_call(zr, video, s_stream, 0); set_videobus_dir(zr, 1); route.input = 1; - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + encoder_call(zr, video, s_routing, &route); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1096,9 +1093,9 @@ zr36057_enable_jpg (struct zoran *zr, jpeg_codec_sleep(zr, 1); zr36057_adjust_vfe(zr, mode); - decoder_command(zr, VIDIOC_STREAMON, 0); + decoder_call(zr, video, s_stream, 1); route.input = 0; - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + encoder_call(zr, video, s_routing, &route); dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr)); break; @@ -1211,7 +1208,7 @@ static void zoran_restart(struct zoran *zr) int status = 0, mode; if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); + decoder_call(zr, video, g_input_status, &status); mode = CODEC_DO_COMPRESSION; } else { status = V4L2_IN_ST_NO_SIGNAL; @@ -1596,14 +1593,14 @@ zoran_init_hardware (struct zoran *zr) route.input = zr->card.input[zr->input].muxsel; - decoder_command(zr, VIDIOC_INT_INIT, NULL); - decoder_command(zr, VIDIOC_S_STD, &zr->norm); - decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_call(zr, core, init, 0); + decoder_s_std(zr, zr->norm); + decoder_s_routing(zr, &route); - encoder_command(zr, VIDIOC_INT_INIT, NULL); - encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &zr->norm); + encoder_call(zr, core, init, 0); + encoder_call(zr, video, s_std_output, zr->norm); route.input = 0; - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + encoder_call(zr, video, s_routing, &route); /* toggle JPEG codec sleep to sync PLL */ jpeg_codec_sleep(zr, 1); @@ -1668,37 +1665,30 @@ zr36057_init_vfe (struct zoran *zr) * Interface to decoder and encoder chips using i2c bus */ -int -decoder_command (struct zoran *zr, - int cmd, - void *data) +int decoder_s_std(struct zoran *zr, v4l2_std_id std) { - if (zr->decoder == NULL) - return -EIO; - - if (zr->card.type == LML33 && - (cmd == VIDIOC_S_STD || cmd == VIDIOC_INT_S_VIDEO_ROUTING)) { - int res; + int res; - // Bt819 needs to reset its FIFO buffer using #FRST pin and - // LML33 card uses GPIO(7) for that. + /* Bt819 needs to reset its FIFO buffer using #FRST pin and + LML33 card uses GPIO(7) for that. */ + if (zr->card.type == LML33) GPIO(zr, 7, 0); - res = zr->decoder->driver->command(zr->decoder, cmd, data); - // Pull #FRST high. - GPIO(zr, 7, 1); - return res; - } else - return zr->decoder->driver->command(zr->decoder, cmd, - data); + res = decoder_call(zr, tuner, s_std, std); + if (zr->card.type == LML33) + GPIO(zr, 7, 1); /* Pull #FRST high. */ + return res; } -int -encoder_command (struct zoran *zr, - int cmd, - void *data) +int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route) { - if (zr->encoder == NULL) - return -1; + int res; - return zr->encoder->driver->command(zr->encoder, cmd, data); + /* Bt819 needs to reset its FIFO buffer using #FRST pin and + LML33 card uses GPIO(7) for that. */ + if (zr->card.type == LML33) + GPIO(zr, 7, 0); + res = decoder_call(zr, video, s_routing, route); + if (zr->card.type == LML33) + GPIO(zr, 7, 1); /* Pull #FRST high. */ + return res; } diff --git a/linux/drivers/media/video/zoran/zoran_device.h b/linux/drivers/media/video/zoran/zoran_device.h index d4e0b9b5a..5f2dd0d41 100644 --- a/linux/drivers/media/video/zoran/zoran_device.h +++ b/linux/drivers/media/video/zoran/zoran_device.h @@ -93,11 +93,12 @@ extern int jpg_bufsize; extern int pass_through; /* i2c */ -extern int decoder_command(struct zoran *zr, - int cmd, - void *data); -extern int encoder_command(struct zoran *zr, - int cmd, - void *data); +#define decoder_call(zr, o, f, args...) \ + v4l2_subdev_call(zr->decoder, o, f, ##args) +#define encoder_call(zr, o, f, args...) \ + v4l2_subdev_call(zr->encoder, o, f, ##args) + +int decoder_s_std(struct zoran *zr, v4l2_std_id std); +int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route); #endif /* __ZORAN_DEVICE_H__ */ diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 66659d479..ef07e51bc 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -964,10 +964,6 @@ static int zoran_open(struct file *file) lock_kernel(); - /* see fs/device.c - the kernel already locks during open(), - * so locking ourselves only causes deadlocks */ - /*mutex_lock(&zr->resource_lock);*/ - if (zr->user >= 2048) { dprintk(1, KERN_ERR "%s: too many users (%d) on device\n", ZR_DEVNAME(zr), zr->user); @@ -975,32 +971,6 @@ static int zoran_open(struct file *file) goto fail_unlock; } - if (!zr->decoder) { - dprintk(1, - KERN_ERR "%s: no TV decoder loaded for device!\n", - ZR_DEVNAME(zr)); - res = -EIO; - goto fail_unlock; - } - - if (!try_module_get(zr->decoder->driver->driver.owner)) { - dprintk(1, - KERN_ERR - "%s: failed to grab ownership of video decoder\n", - ZR_DEVNAME(zr)); - res = -EIO; - goto fail_unlock; - } - if (zr->encoder && - !try_module_get(zr->encoder->driver->driver.owner)) { - dprintk(1, - KERN_ERR - "%s: failed to grab ownership of video encoder\n", - ZR_DEVNAME(zr)); - res = -EIO; - goto fail_decoder; - } - /* now, create the open()-specific file_ops struct */ fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL); if (!fh) { @@ -1009,7 +979,7 @@ static int zoran_open(struct file *file) "%s: zoran_open() - allocation of zoran_fh failed\n", ZR_DEVNAME(zr)); res = -ENOMEM; - goto fail_encoder; + goto fail_unlock; } /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows * on norm-change! */ @@ -1048,11 +1018,6 @@ static int zoran_open(struct file *file) fail_fh: kfree(fh); -fail_encoder: - if (zr->encoder) - module_put(zr->encoder->driver->driver.owner); -fail_decoder: - module_put(zr->decoder->driver->driver.owner); fail_unlock: unlock_kernel(); @@ -1105,8 +1070,8 @@ zoran_close(struct file *file) if (!pass_through) { /* Switch to color bar */ struct v4l2_routing route = { 2, 0 }; - decoder_command(zr, VIDIOC_STREAMOFF, 0); - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_call(zr, video, s_stream, 0); + encoder_call(zr, video, s_routing, &route); } } @@ -1114,13 +1079,6 @@ zoran_close(struct file *file) kfree(fh->overlay_mask); kfree(fh); - /* release locks on the i2c modules */ - module_put(zr->decoder->driver->driver.owner); - if (zr->encoder) - module_put(zr->encoder->driver->driver.owner); - - /*mutex_unlock(&zr->resource_lock);*/ - dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr)); return 0; @@ -1568,20 +1526,20 @@ zoran_set_norm (struct zoran *zr, int status = 0; v4l2_std_id std = 0; - decoder_command(zr, VIDIOC_QUERYSTD, &std); - decoder_command(zr, VIDIOC_S_STD, &std); + decoder_call(zr, video, querystd, &std); + decoder_s_std(zr, std); /* let changes come into effect */ ssleep(2); - decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); + decoder_call(zr, video, g_input_status, &status); if (status & V4L2_IN_ST_NO_SIGNAL) { dprintk(1, KERN_ERR "%s: set_norm() - no norm detected\n", ZR_DEVNAME(zr)); /* reset norm */ - decoder_command(zr, VIDIOC_S_STD, &zr->norm); + decoder_s_std(zr, zr->norm); return -EIO; } @@ -1600,8 +1558,8 @@ zoran_set_norm (struct zoran *zr, if (on) zr36057_overlay(zr, 0); - decoder_command(zr, VIDIOC_S_STD, &norm); - encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &norm); + decoder_s_std(zr, norm); + encoder_call(zr, video, s_std_output, norm); if (on) zr36057_overlay(zr, 1); @@ -1642,7 +1600,7 @@ zoran_set_input (struct zoran *zr, route.input = zr->card.input[input].muxsel; zr->input = input; - decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_s_routing(zr, &route); return 0; } @@ -1887,18 +1845,18 @@ jpgreqbuf_unlock_and_return: goto gstat_unlock_and_return; } - decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_s_routing(zr, &route); /* sleep 1 second */ ssleep(1); /* Get status of video decoder */ - decoder_command(zr, VIDIOC_QUERYSTD, &norm); - decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); + decoder_call(zr, video, querystd, &norm); + decoder_call(zr, video, g_input_status, &status); /* restore previous input and norm */ route.input = zr->card.input[zr->input].muxsel; - decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_s_routing(zr, &route); gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); @@ -2837,7 +2795,7 @@ static int zoran_queryctrl(struct file *file, void *__fh, ctrl->id > V4L2_CID_HUE) return -EINVAL; - decoder_command(zr, VIDIOC_QUERYCTRL, ctrl); + decoder_call(zr, core, queryctrl, ctrl); return 0; } @@ -2853,7 +2811,7 @@ static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl return -EINVAL; mutex_lock(&zr->resource_lock); - decoder_command(zr, VIDIOC_G_CTRL, ctrl); + decoder_call(zr, core, g_ctrl, ctrl); mutex_unlock(&zr->resource_lock); return 0; @@ -2870,7 +2828,7 @@ static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl return -EINVAL; mutex_lock(&zr->resource_lock); - decoder_command(zr, VIDIOC_S_CTRL, ctrl); + decoder_call(zr, core, s_ctrl, ctrl); mutex_unlock(&zr->resource_lock); return 0; @@ -2925,7 +2883,7 @@ static int zoran_enum_input(struct file *file, void *__fh, /* Get status of video decoder */ mutex_lock(&zr->resource_lock); - decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &inp->status); + decoder_call(zr, video, g_input_status, &inp->status); mutex_unlock(&zr->resource_lock); return 0; } -- cgit v1.2.3 From 58dfb1e7efa2bd70a814acae3d512733168feb95 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 21:31:17 +0100 Subject: v4l-dvb: cleanup obsolete references to v4l1 headers. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/tuners/mt20xx.c | 2 +- linux/drivers/media/common/tuners/tda8290.c | 2 +- linux/drivers/media/common/tuners/tea5761.c | 2 +- linux/drivers/media/common/tuners/tea5767.c | 2 +- linux/drivers/media/video/ks0127.h | 2 -- linux/drivers/media/video/saa6588.c | 2 +- linux/drivers/media/video/tvaudio.c | 2 +- linux/drivers/media/video/tvmixer.c | 2 +- linux/drivers/media/video/zoran/videocodec.h | 9 ++---- linux/drivers/media/video/zoran/zoran.h | 8 ++++- linux/drivers/media/video/zoran/zoran_card.c | 43 ++++++-------------------- linux/drivers/media/video/zoran/zoran_device.c | 20 ++++++------ linux/drivers/media/video/zoran/zoran_device.h | 2 +- linux/drivers/media/video/zoran/zoran_driver.c | 40 ++++++++++++------------ linux/drivers/media/video/zoran/zoran_procfs.c | 2 +- linux/drivers/media/video/zoran/zr36016.c | 5 --- linux/drivers/media/video/zoran/zr36050.c | 4 --- linux/drivers/media/video/zoran/zr36060.c | 4 --- 18 files changed, 57 insertions(+), 96 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/mt20xx.c b/linux/drivers/media/common/tuners/mt20xx.c index 2669cd0bf..307a8f8dd 100644 --- a/linux/drivers/media/common/tuners/mt20xx.c +++ b/linux/drivers/media/common/tuners/mt20xx.c @@ -7,7 +7,7 @@ #include #include #include "compat.h" -#include +#include #include "tuner-i2c.h" #include "mt20xx.h" diff --git a/linux/drivers/media/common/tuners/tda8290.c b/linux/drivers/media/common/tuners/tda8290.c index 54423df4c..b1ef5f1e4 100644 --- a/linux/drivers/media/common/tuners/tda8290.c +++ b/linux/drivers/media/common/tuners/tda8290.c @@ -23,7 +23,7 @@ #include #include #include "compat.h" -#include +#include #include "tuner-i2c.h" #include "tda8290.h" #include "tda827x.h" diff --git a/linux/drivers/media/common/tuners/tea5761.c b/linux/drivers/media/common/tuners/tea5761.c index f5fadcd4b..d13490f77 100644 --- a/linux/drivers/media/common/tuners/tea5761.c +++ b/linux/drivers/media/common/tuners/tea5761.c @@ -10,7 +10,7 @@ #include #include #include "compat.h" -#include +#include #include #include "tuner-i2c.h" #include "tea5761.h" diff --git a/linux/drivers/media/common/tuners/tea5767.c b/linux/drivers/media/common/tuners/tea5767.c index c56ff2dc1..2fb5be7f0 100644 --- a/linux/drivers/media/common/tuners/tea5767.c +++ b/linux/drivers/media/common/tuners/tea5767.c @@ -13,7 +13,7 @@ #include #include #include "compat.h" -#include +#include #include "tuner-i2c.h" #include "tea5767.h" diff --git a/linux/drivers/media/video/ks0127.h b/linux/drivers/media/video/ks0127.h index 1ec578833..cb8abd540 100644 --- a/linux/drivers/media/video/ks0127.h +++ b/linux/drivers/media/video/ks0127.h @@ -24,8 +24,6 @@ #ifndef KS0127_H #define KS0127_H -#include - /* input channels */ #define KS_INPUT_COMPOSITE_1 0 #define KS_INPUT_COMPOSITE_2 1 diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index 77c3b59e8..ae96de5fd 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 3ca242af5..db03d1350 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/linux/drivers/media/video/tvmixer.c b/linux/drivers/media/video/tvmixer.c index ae25f0d16..bc6702a0a 100644 --- a/linux/drivers/media/video/tvmixer.c +++ b/linux/drivers/media/video/tvmixer.c @@ -11,7 +11,7 @@ #include #include #include "compat.h" -#include +#include #include #include #include diff --git a/linux/drivers/media/video/zoran/videocodec.h b/linux/drivers/media/video/zoran/videocodec.h index 1b40df14f..5fc11caf2 100644 --- a/linux/drivers/media/video/zoran/videocodec.h +++ b/linux/drivers/media/video/zoran/videocodec.h @@ -97,7 +97,7 @@ available) - it returns 0 if the mode is possible set_size -> this fn-ref. sets the norm and image size for compression/decompression (returns 0 on success) - the norm param is defined in videodev.h (VIDEO_MODE_*) + the norm param is defined in videodev2.h (V4L2_STD_*) additional setup may be available, too - but the codec should work with some default values even without this @@ -145,9 +145,8 @@ M zr36055[1] 0001 0000c001 00000000 (zr36050[1]) #define __LINUX_VIDEOCODEC_H #include "compat.h" -#include +#include -//should be in videodev.h ??? (VID_DO_....) #define CODEC_DO_COMPRESSION 0 #define CODEC_DO_EXPANSION 1 @@ -238,10 +237,6 @@ struct vfe_settings { __u32 width, height; /* Area to capture */ __u16 decimation; /* Decimation divider */ __u16 flags; /* Flags for capture */ -/* flags are the same as in struct video_capture - see videodev.h: -#define VIDEO_CAPTURE_ODD 0 -#define VIDEO_CAPTURE_EVEN 1 -*/ __u16 quality; /* quality of the video */ }; diff --git a/linux/drivers/media/video/zoran/zoran.h b/linux/drivers/media/video/zoran/zoran.h index ab1ced262..8beada961 100644 --- a/linux/drivers/media/video/zoran/zoran.h +++ b/linux/drivers/media/video/zoran/zoran.h @@ -408,7 +408,13 @@ struct zoran { /* Video for Linux parameters */ int input; /* card's norm and input - norm=VIDEO_MODE_* */ v4l2_std_id norm; - struct video_buffer buffer; /* Current buffer params */ + + /* Current buffer params */ + void *vbuf_base; + int vbuf_height, vbuf_width; + int vbuf_depth; + int vbuf_bytesperline; + struct zoran_overlay_settings overlay_settings; u32 *overlay_mask; /* overlay mask */ enum zoran_lock_activity overlay_active; /* feature currently in use? */ diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index f60fba83a..f786e15ab 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -39,7 +39,7 @@ #include #include #include "compat.h" -#include +#include #include #include #include @@ -48,8 +48,6 @@ #include #include -#include -#include #include #include @@ -109,23 +107,6 @@ static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; module_param_array(video_nr, int, NULL, 0444); MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); -/* - Number and size of grab buffers for Video 4 Linux - The vast majority of applications should not need more than 2, - the very popular BTTV driver actually does ONLY have 2. - Time sensitive applications might need more, the maximum - is VIDEO_MAX_FRAME (defined in ). - - The size is set so that the maximum possible request - can be satisfied. Decrease it, if bigphys_area alloc'd - memory is low. If you don't have the bigphys_area patch, - set it to 128 KB. Will you allow only to grab small - images with V4L, but that's better than nothing. - - v4l_bufsize has to be given in KB ! - -*/ - int v4l_nbufs = 4; int v4l_bufsize = 810; /* Everybody should be able to work with this setting */ module_param(v4l_nbufs, int, 0644); @@ -1037,20 +1018,19 @@ zr36057_init (struct zoran *zr) zr->jpg_buffers.allocated = 0; zr->v4l_buffers.allocated = 0; - zr->buffer.base = (void *) vidmem; - zr->buffer.width = 0; - zr->buffer.height = 0; - zr->buffer.depth = 0; - zr->buffer.bytesperline = 0; + zr->vbuf_base = (void *) vidmem; + zr->vbuf_width = 0; + zr->vbuf_height = 0; + zr->vbuf_depth = 0; + zr->vbuf_bytesperline = 0; /* Avoid nonsense settings from user for default input/norm */ - if (default_norm < VIDEO_MODE_PAL && - default_norm > VIDEO_MODE_SECAM) - default_norm = VIDEO_MODE_PAL; - if (default_norm == VIDEO_MODE_PAL) { + if (default_norm < 0 && default_norm > 2) + default_norm = 0; + if (default_norm == 0) { zr->norm = V4L2_STD_PAL; zr->timing = zr->card.tvn[0]; - } else if (default_norm == VIDEO_MODE_NTSC) { + } else if (default_norm == 1) { zr->norm = V4L2_STD_NTSC; zr->timing = zr->card.tvn[1]; } else { @@ -1548,9 +1528,6 @@ static int __init zoran_init(void) ZORAN_NAME, vidmem); } - /* random nonsense */ - dprintk(6, KERN_DEBUG "Jotti is een held!\n"); - /* some mainboards might not do PCI-PCI data transfer well */ if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) { dprintk(1, diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index fc1be816d..c2dfd4b67 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -489,11 +489,11 @@ zr36057_overlay (struct zoran *zr, * All error messages are internal driver checking only! */ /* video display top and bottom registers */ - reg = (long) zr->buffer.base + + reg = (long) zr->vbuf_base + zr->overlay_settings.x * ((zr->overlay_settings.format->depth + 7) / 8) + zr->overlay_settings.y * - zr->buffer.bytesperline; + zr->vbuf_bytesperline; btwrite(reg, ZR36057_VDTR); if (reg & 3) dprintk(1, @@ -501,15 +501,15 @@ zr36057_overlay (struct zoran *zr, "%s: zr36057_overlay() - video_address not aligned\n", ZR_DEVNAME(zr)); if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2) - reg += zr->buffer.bytesperline; + reg += zr->vbuf_bytesperline; btwrite(reg, ZR36057_VDBR); /* video stride, status, and frame grab register */ - reg = zr->buffer.bytesperline - + reg = zr->vbuf_bytesperline - zr->overlay_settings.width * ((zr->overlay_settings.format->depth + 7) / 8); if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2) - reg += zr->buffer.bytesperline; + reg += zr->vbuf_bytesperline; if (reg & 3) dprintk(1, KERN_ERR @@ -538,7 +538,7 @@ zr36057_overlay (struct zoran *zr, void write_overlay_mask (struct file *file, - struct video_clip *vp, + struct v4l2_clip *vp, int count) { struct zoran_fh *fh = file->private_data; @@ -555,10 +555,10 @@ write_overlay_mask (struct file *file, for (i = 0; i < count; ++i) { /* pick up local copy of clip */ - x = vp[i].x; - y = vp[i].y; - width = vp[i].width; - height = vp[i].height; + x = vp[i].c.left; + y = vp[i].c.top; + width = vp[i].c.width; + height = vp[i].c.height; /* trim clips that extend beyond the window */ if (x < 0) { diff --git a/linux/drivers/media/video/zoran/zoran_device.h b/linux/drivers/media/video/zoran/zoran_device.h index 5f2dd0d41..2eb645904 100644 --- a/linux/drivers/media/video/zoran/zoran_device.h +++ b/linux/drivers/media/video/zoran/zoran_device.h @@ -55,7 +55,7 @@ extern int jpeg_codec_reset(struct zoran *zr); extern void zr36057_overlay(struct zoran *zr, int on); extern void write_overlay_mask(struct file *file, - struct video_clip *vp, + struct v4l2_clip *vp, int count); extern void zr36057_set_memgrab(struct zoran *zr, int mode); diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index ef07e51bc..b2e7ce15c 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -59,7 +59,7 @@ #include -#include +#include #include #include #include "videocodec.h" @@ -69,8 +69,6 @@ #include #include -#include -#include #include "compat.h" #include #include "zoran.h" @@ -1171,12 +1169,12 @@ setup_fbuffer (struct file *file, return -EINVAL; } - zr->buffer.base = (void *) ((unsigned long) base & ~3); - zr->buffer.height = height; - zr->buffer.width = width; - zr->buffer.depth = fmt->depth; + zr->vbuf_base = (void *) ((unsigned long) base & ~3); + zr->vbuf_height = height; + zr->vbuf_width = width; + zr->vbuf_depth = fmt->depth; zr->overlay_settings.format = fmt; - zr->buffer.bytesperline = bytesperline; + zr->vbuf_bytesperline = bytesperline; /* The user should set new window parameters */ zr->overlay_settings.is_set = 0; @@ -1191,17 +1189,17 @@ setup_window (struct file *file, int y, int width, int height, - struct video_clip __user *clips, + struct v4l2_clip __user *clips, int clipcount, void __user *bitmap) { struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; - struct video_clip *vcp = NULL; + struct v4l2_clip *vcp = NULL; int on, end; - if (!zr->buffer.base) { + if (!zr->vbuf_base) { dprintk(1, KERN_ERR "%s: setup_window() - frame buffer has to be set first\n", @@ -1221,13 +1219,13 @@ setup_window (struct file *file, * The video front end needs 4-byte alinged line sizes, we correct that * silently here if necessary */ - if (zr->buffer.depth == 15 || zr->buffer.depth == 16) { + if (zr->vbuf_depth == 15 || zr->vbuf_depth == 16) { end = (x + width) & ~1; /* round down */ x = (x + 1) & ~1; /* round up */ width = end - x; } - if (zr->buffer.depth == 24) { + if (zr->vbuf_depth == 24) { end = (x + width) & ~3; /* round down */ x = (x + 3) & ~3; /* round up */ width = end - x; @@ -1282,7 +1280,7 @@ setup_window (struct file *file, } } else if (clipcount > 0) { /* write our own bitmap from the clips */ - vcp = vmalloc(sizeof(struct video_clip) * (clipcount + 4)); + vcp = vmalloc(sizeof(struct v4l2_clip) * (clipcount + 4)); if (vcp == NULL) { dprintk(1, KERN_ERR @@ -1291,7 +1289,7 @@ setup_window (struct file *file, return -ENOMEM; } if (copy_from_user - (vcp, clips, sizeof(struct video_clip) * clipcount)) { + (vcp, clips, sizeof(struct v4l2_clip) * clipcount)) { vfree(vcp); return -EFAULT; } @@ -1350,7 +1348,7 @@ setup_overlay (struct file *file, zr36057_overlay(zr, 0); zr->overlay_mask = NULL; } else { - if (!zr->buffer.base || !fh->overlay_settings.is_set) { + if (!zr->vbuf_base || !fh->overlay_settings.is_set) { dprintk(1, KERN_ERR "%s: setup_overlay() - buffer or window not set\n", @@ -2201,7 +2199,7 @@ static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh, fmt->fmt.win.w.top, fmt->fmt.win.w.width, fmt->fmt.win.w.height, - (struct video_clip __user *) + (struct v4l2_clip __user *) fmt->fmt.win.clips, fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); @@ -2358,12 +2356,12 @@ static int zoran_g_fbuf(struct file *file, void *__fh, memset(fb, 0, sizeof(*fb)); mutex_lock(&zr->resource_lock); - fb->base = zr->buffer.base; - fb->fmt.width = zr->buffer.width; - fb->fmt.height = zr->buffer.height; + fb->base = zr->vbuf_base; + fb->fmt.width = zr->vbuf_width; + fb->fmt.height = zr->vbuf_height; if (zr->overlay_settings.format) fb->fmt.pixelformat = fh->overlay_settings.format->fourcc; - fb->fmt.bytesperline = zr->buffer.bytesperline; + fb->fmt.bytesperline = zr->vbuf_bytesperline; mutex_unlock(&zr->resource_lock); fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; fb->fmt.field = V4L2_FIELD_INTERLACED; diff --git a/linux/drivers/media/video/zoran/zoran_procfs.c b/linux/drivers/media/video/zoran/zoran_procfs.c index 961950a21..89c49a5cf 100644 --- a/linux/drivers/media/video/zoran/zoran_procfs.c +++ b/linux/drivers/media/video/zoran/zoran_procfs.c @@ -37,7 +37,7 @@ #include #include #include "compat.h" -#include +#include #include #include #include diff --git a/linux/drivers/media/video/zoran/zr36016.c b/linux/drivers/media/video/zoran/zr36016.c index 693a648e9..7d8d5b195 100644 --- a/linux/drivers/media/video/zoran/zr36016.c +++ b/linux/drivers/media/video/zoran/zr36016.c @@ -34,16 +34,11 @@ #include #include -/* includes for structures and defines regarding video - #include */ - /* I/O commands, error codes */ #include -//#include /* v4l API */ #include "compat.h" -#include /* headerfile of this module */ #include"zr36016.h" diff --git a/linux/drivers/media/video/zoran/zr36050.c b/linux/drivers/media/video/zoran/zr36050.c index cf8b271a1..639dd87c6 100644 --- a/linux/drivers/media/video/zoran/zr36050.c +++ b/linux/drivers/media/video/zoran/zr36050.c @@ -34,12 +34,8 @@ #include #include -/* includes for structures and defines regarding video - #include */ - /* I/O commands, error codes */ #include -//#include /* headerfile of this module */ #include "zr36050.h" diff --git a/linux/drivers/media/video/zoran/zr36060.c b/linux/drivers/media/video/zoran/zr36060.c index 8e74054d5..008746ff7 100644 --- a/linux/drivers/media/video/zoran/zr36060.c +++ b/linux/drivers/media/video/zoran/zr36060.c @@ -34,12 +34,8 @@ #include #include -/* includes for structures and defines regarding video - #include */ - /* I/O commands, error codes */ #include -//#include /* headerfile of this module */ #include "zr36060.h" -- cgit v1.2.3 From 92b6b4bed8a77876fa7889ee8bcc86798ccc3762 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 21:41:19 +0100 Subject: zoran i2c modules: remove i2c autoprobing support. From: Hans Verkuil Zoran doesn't do autoprobing anymore, so remove support for this from the i2c modules. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/adv7170.c | 11 +++-------- linux/drivers/media/video/adv7175.c | 11 +++-------- linux/drivers/media/video/bt819.c | 11 +++-------- linux/drivers/media/video/bt856.c | 11 +++-------- linux/drivers/media/video/bt866.c | 17 +++-------------- linux/drivers/media/video/ks0127.c | 19 ++++--------------- linux/drivers/media/video/saa7110.c | 11 +++-------- linux/drivers/media/video/saa7127.c | 1 - linux/drivers/media/video/saa7185.c | 11 +++-------- linux/drivers/media/video/vpx3220.c | 11 +++-------- 10 files changed, 28 insertions(+), 86 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 6dd63d36c..87bc8ed46 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -37,13 +37,14 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ @@ -51,6 +52,7 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +#endif static int debug; module_param(debug, int, 0); @@ -272,11 +274,6 @@ static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7170, 0); } -static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops adv7170_core_ops = { @@ -351,8 +348,6 @@ MODULE_DEVICE_TABLE(i2c, adv7170_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "adv7170", - .driverid = I2C_DRIVERID_ADV7170, - .command = adv7170_command, .probe = adv7170_probe, .remove = adv7170_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c index 61ab7b165..dc036d2fa 100644 --- a/linux/drivers/media/video/adv7175.c +++ b/linux/drivers/media/video/adv7175.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); @@ -43,6 +43,7 @@ MODULE_LICENSE("GPL"); #define I2C_ADV7175 0xd4 #define I2C_ADV7176 0x54 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, @@ -50,6 +51,7 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +#endif static int debug; module_param(debug, int, 0); @@ -310,11 +312,6 @@ static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0); } -static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops adv7175_core_ops = { @@ -390,8 +387,6 @@ MODULE_DEVICE_TABLE(i2c, adv7175_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "adv7175", - .driverid = I2C_DRIVERID_ADV7175, - .command = adv7175_command, .probe = adv7175_probe, .remove = adv7175_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index 4d44df52b..ec64197e9 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); @@ -49,9 +49,11 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ @@ -429,11 +431,6 @@ static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); } -static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops bt819_core_ops = { @@ -540,8 +537,6 @@ MODULE_DEVICE_TABLE(i2c, bt819_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "bt819", - .driverid = I2C_DRIVERID_BT819, - .command = bt819_command, .probe = bt819_probe, .remove = bt819_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c index 96def6283..fc7b64d91 100644 --- a/linux/drivers/media/video/bt856.c +++ b/linux/drivers/media/video/bt856.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); @@ -48,9 +48,11 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ @@ -188,11 +190,6 @@ static int bt856_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT856, 0); } -static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops bt856_core_ops = { @@ -273,8 +270,6 @@ MODULE_DEVICE_TABLE(i2c, bt856_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "bt856", - .driverid = I2C_DRIVERID_BT856, - .command = bt856_command, .probe = bt856_probe, .remove = bt856_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index 9f53b8176..edc1aa348 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); @@ -48,9 +48,11 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ @@ -186,11 +188,6 @@ static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); } -static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops bt866_core_ops = { @@ -233,11 +230,6 @@ static int bt866_remove(struct i2c_client *client) return 0; } -static int bt866_legacy_probe(struct i2c_adapter *adapter) -{ - return adapter->id == I2C_HW_B_ZR36067; -} - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id bt866_id[] = { { "bt866", 0 }, @@ -248,11 +240,8 @@ MODULE_DEVICE_TABLE(i2c, bt866_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "bt866", - .driverid = I2C_DRIVERID_BT866, - .command = bt866_command, .probe = bt866_probe, .remove = bt866_remove, - .legacy_probe = bt866_legacy_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = bt866_id, #endif diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index 309f61ca4..eaa481a57 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include "ks0127.h" #include "compat.h" @@ -50,10 +50,11 @@ MODULE_DESCRIPTION("KS0127 video decoder driver"); MODULE_AUTHOR("Ryan Drake"); MODULE_LICENSE("GPL"); -/* Addresses to scan */ +/* Addresses */ #define I2C_KS0127_ADDON 0xD8 #define I2C_KS0127_ONBOARD 0xDA +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { I2C_KS0127_ADDON >> 1, I2C_KS0127_ONBOARD >> 1, @@ -61,6 +62,7 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +#endif /* ks0127 control registers */ #define KS_STAT 0x00 @@ -651,11 +653,6 @@ static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_iden return v4l2_chip_ident_i2c_client(client, chip, ks->ident, 0); } -static int ks0127_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ks0127_core_ops = { @@ -718,11 +715,6 @@ static int ks0127_remove(struct i2c_client *client) return 0; } -static int ks0127_legacy_probe(struct i2c_adapter *adapter) -{ - return adapter->id == I2C_HW_B_ZR36067; -} - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id ks0127_id[] = { { "ks0127", 0 }, @@ -735,11 +727,8 @@ MODULE_DEVICE_TABLE(i2c, ks0127_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "ks0127", - .driverid = I2C_DRIVERID_KS0127, - .command = ks0127_command, .probe = ks0127_probe, .remove = ks0127_remove, - .legacy_probe = ks0127_legacy_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = ks0127_id, #endif diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index 132ef1812..c417b7007 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -36,16 +36,18 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); MODULE_AUTHOR("Pauline Middelink"); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif static int debug; module_param(debug, int, 0); @@ -409,11 +411,6 @@ static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0); } -static int saa7110_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7110_core_ops = { @@ -519,8 +516,6 @@ MODULE_DEVICE_TABLE(i2c, saa7110_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7110", - .driverid = I2C_DRIVERID_SAA7110, - .command = saa7110_command, .probe = saa7110_probe, .remove = saa7110_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c index c6ddb476c..9beef8886 100644 --- a/linux/drivers/media/video/saa7127.c +++ b/linux/drivers/media/video/saa7127.c @@ -826,7 +826,6 @@ MODULE_DEVICE_TABLE(i2c, saa7127_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7127", - .driverid = I2C_DRIVERID_SAA7127, .probe = saa7127_probe, .remove = saa7127_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c index 4c20f0377..290299451 100644 --- a/linux/drivers/media/video/saa7185.c +++ b/linux/drivers/media/video/saa7185.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); @@ -44,9 +44,11 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ @@ -296,11 +298,6 @@ static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0); } -static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7185_core_ops = { @@ -377,8 +374,6 @@ MODULE_DEVICE_TABLE(i2c, saa7185_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7185", - .driverid = I2C_DRIVERID_SAA7185B, - .command = saa7185_command, .probe = saa7185_probe, .remove = saa7185_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index 1f250229c..0c1c97f2f 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); @@ -38,9 +38,11 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif #define VPX_TIMEOUT_COUNT 10 @@ -526,11 +528,6 @@ static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); } -static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops vpx3220_core_ops = { @@ -643,8 +640,6 @@ MODULE_DEVICE_TABLE(i2c, vpx3220_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "vpx3220", - .driverid = I2C_DRIVERID_VPX3220, - .command = vpx3220_command, .probe = vpx3220_probe, .remove = vpx3220_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From b2e7077468076b3bfb3f6ad572808dab4a8795ae Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 20 Feb 2009 09:50:52 +0100 Subject: v4l2: add colorfx support to v4l2-common.c, and add to 'Changes' in spec. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 8ae8dd366..ec81afb19 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -335,6 +335,12 @@ const char **v4l2_ctrl_get_menu(u32 id) "Aperture Priority Mode", NULL }; + static const char *colorfx[] = { + "None", + "Black & White", + "Sepia", + NULL + }; switch (id) { case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: @@ -371,6 +377,8 @@ const char **v4l2_ctrl_get_menu(u32 id) return camera_power_line_frequency; case V4L2_CID_EXPOSURE_AUTO: return camera_exposure_auto; + case V4L2_CID_COLORFX: + return colorfx; default: return NULL; } @@ -413,6 +421,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation"; case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; case V4L2_CID_COLOR_KILLER: return "Color Killer"; + case V4L2_CID_COLORFX: return "Color Effects"; /* MPEG controls */ case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; @@ -518,6 +527,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_MPEG_STREAM_TYPE: case V4L2_CID_MPEG_STREAM_VBI_FMT: case V4L2_CID_EXPOSURE_AUTO: + case V4L2_CID_COLORFX: qctrl->type = V4L2_CTRL_TYPE_MENU; step = 1; break; @@ -586,6 +596,8 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0); + case V4L2_CID_COLORFX: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); /* MPEG controls */ case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: -- cgit v1.2.3 From 28258187ce09827121e04b2de19e454032427d96 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 20 Feb 2009 10:30:12 +0100 Subject: v4l2-common/v4l2-spec: support/document write-only and button controls From: Hans Verkuil The controls V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET changed their type to button controls (these are unused at the moment, so this is a safe change). The controls V4L2_CID_PAN_RELATIVE, V4L2_CID_TILT_RELATIVE, V4L2_CID_FOCUS_RELATIVE and V4L2_CID_ZOOM_RELATIVE are marked as write-only controls. Priority: normal Signed-off-by: Hans Verkuil CC: Laurent Pinchart --- linux/drivers/media/video/v4l2-common.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index ec81afb19..c2d71816e 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -391,16 +391,16 @@ const char *v4l2_ctrl_get_name(u32 id) switch (id) { /* USER controls */ case V4L2_CID_USER_CLASS: return "User Controls"; + case V4L2_CID_BRIGHTNESS: return "Brightness"; + case V4L2_CID_CONTRAST: return "Contrast"; + case V4L2_CID_SATURATION: return "Saturation"; + case V4L2_CID_HUE: return "Hue"; case V4L2_CID_AUDIO_VOLUME: return "Volume"; - case V4L2_CID_AUDIO_MUTE: return "Mute"; case V4L2_CID_AUDIO_BALANCE: return "Balance"; case V4L2_CID_AUDIO_BASS: return "Bass"; case V4L2_CID_AUDIO_TREBLE: return "Treble"; + case V4L2_CID_AUDIO_MUTE: return "Mute"; case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; - case V4L2_CID_BRIGHTNESS: return "Brightness"; - case V4L2_CID_CONTRAST: return "Contrast"; - case V4L2_CID_SATURATION: return "Saturation"; - case V4L2_CID_HUE: return "Hue"; case V4L2_CID_BLACK_LEVEL: return "Black Level"; case V4L2_CID_AUTO_WHITE_BALANCE: return "White Balance, Automatic"; case V4L2_CID_DO_WHITE_BALANCE: return "Do White Balance"; @@ -500,16 +500,25 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_HFLIP: case V4L2_CID_VFLIP: case V4L2_CID_HUE_AUTO: + case V4L2_CID_CHROMA_AGC: + case V4L2_CID_COLOR_KILLER: case V4L2_CID_MPEG_AUDIO_MUTE: case V4L2_CID_MPEG_VIDEO_MUTE: case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: case V4L2_CID_MPEG_VIDEO_PULLDOWN: case V4L2_CID_EXPOSURE_AUTO_PRIORITY: + case V4L2_CID_FOCUS_AUTO: case V4L2_CID_PRIVACY: qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; min = 0; max = step = 1; break; + case V4L2_CID_PAN_RESET: + case V4L2_CID_TILT_RESET: + qctrl->type = V4L2_CTRL_TYPE_BUTTON; + qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; + min = max = step = def = 0; + break; case V4L2_CID_POWER_LINE_FREQUENCY: case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: case V4L2_CID_MPEG_AUDIO_ENCODING: @@ -558,8 +567,17 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: case V4L2_CID_HUE: + case V4L2_CID_RED_BALANCE: + case V4L2_CID_BLUE_BALANCE: + case V4L2_CID_GAMMA: qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; break; + case V4L2_CID_PAN_RELATIVE: + case V4L2_CID_TILT_RELATIVE: + case V4L2_CID_FOCUS_RELATIVE: + case V4L2_CID_ZOOM_RELATIVE: + qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; + break; } qctrl->minimum = min; qctrl->maximum = max; @@ -579,6 +597,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) /* USER controls */ case V4L2_CID_USER_CLASS: case V4L2_CID_MPEG_CLASS: + case V4L2_CID_CAMERA_CLASS: return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); case V4L2_CID_AUDIO_VOLUME: return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880); -- cgit v1.2.3 From d3f2882c7b2e1bdf197ad60cfaf4732858d0e708 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 20 Feb 2009 11:34:28 +0100 Subject: zoran: s_jpegcomp should return a proper result, not 0. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index b2e7ce15c..7ddbdf37d 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -3120,7 +3120,7 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, sjpegc_unlock_and_return: mutex_unlock(&zr->resource_lock); - return 0; + return res; } static unsigned int -- cgit v1.2.3 From 1e4553680f02af66c3282072f581425637b58f78 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 20 Feb 2009 19:06:59 +0100 Subject: zoran: increase bufsize to a value suitable for 768x576. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index f786e15ab..57cc62d82 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -108,7 +108,7 @@ module_param_array(video_nr, int, NULL, 0444); MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); int v4l_nbufs = 4; -int v4l_bufsize = 810; /* Everybody should be able to work with this setting */ +int v4l_bufsize = 864; /* Everybody should be able to work with this setting */ module_param(v4l_nbufs, int, 0644); MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use"); module_param(v4l_bufsize, int, 0644); -- cgit v1.2.3 From d649a4d46ae66654680799c6ee8c72cdd610658e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 21 Feb 2009 22:08:41 +0100 Subject: v4l2-common: add v4l2_i2c_subdev_addr() From: Hans Verkuil Add small function to retrieve the i2c address from a v4l2_subdev pointer. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 8ae8dd366..78063b055 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -1049,6 +1049,15 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, } EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); +/* Return i2c client address of v4l2_subdev. */ +unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return client ? client->addr : I2C_CLIENT_END; +} +EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr); + /* Return a list of I2C tuner addresses to probe. Use only if the tuner addresses are unknown. */ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) -- cgit v1.2.3 From c25f637daca2ca532f5cf0bb6f32decb8308953c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 21 Feb 2009 22:11:31 +0100 Subject: usbvision: convert to v4l2_device/v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- .../drivers/media/video/usbvision/usbvision-core.c | 2 +- .../drivers/media/video/usbvision/usbvision-i2c.c | 147 ++++++--------------- .../media/video/usbvision/usbvision-video.c | 63 ++++----- linux/drivers/media/video/usbvision/usbvision.h | 8 +- 4 files changed, 75 insertions(+), 145 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 440f1b05a..412149bbe 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -2654,7 +2654,7 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) } route.input = mode[channel]; route.output = 0; - call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); + call_all(usbvision, video, s_routing, &route); usbvision_set_audio(usbvision, audio[channel]); return 0; } diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.c b/linux/drivers/media/video/usbvision/usbvision-i2c.c index 4c74861f4..addc1716e 100644 --- a/linux/drivers/media/video/usbvision/usbvision-i2c.c +++ b/linux/drivers/media/video/usbvision/usbvision-i2c.c @@ -206,72 +206,78 @@ static struct i2c_algorithm usbvision_algo = { }; -/* - * registering functions to load algorithms at runtime - */ -static int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) -{ - PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); - PDEBUG(DBG_I2C, "ALGO debugging is enabled [i2c]"); - - /* register new adapter to i2c module... */ - - adap->algo = &usbvision_algo; - - adap->timeout = 100; /* default values, should */ - adap->retries = 3; /* be replaced by defines */ - - i2c_add_adapter(adap); - - PDEBUG(DBG_I2C,"i2c bus for %s registered", adap->name); - - return 0; -} - /* ----------------------------------------------------------------------- */ /* usbvision specific I2C functions */ /* ----------------------------------------------------------------------- */ static struct i2c_adapter i2c_adap_template; -static struct i2c_client i2c_client_template; int usbvision_i2c_register(struct usb_usbvision *usbvision) { + static unsigned short saa711x_addrs[] = { + 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ + 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ + I2C_CLIENT_END }; + memcpy(&usbvision->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter)); - memcpy(&usbvision->i2c_client, &i2c_client_template, - sizeof(struct i2c_client)); sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), " #%d", usbvision->vdev->num); PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; - i2c_set_adapdata(&usbvision->i2c_adap, usbvision); - i2c_set_clientdata(&usbvision->i2c_client, usbvision); - - usbvision->i2c_client.adapter = &usbvision->i2c_adap; + i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { printk(KERN_ERR "usbvision_register: can't write reg\n"); return -EBUSY; } -#ifdef CONFIG_MODULES + PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); + PDEBUG(DBG_I2C, "ALGO debugging is enabled [i2c]"); + + /* register new adapter to i2c module... */ + + usbvision->i2c_adap.algo = &usbvision_algo; + + usbvision->i2c_adap.timeout = 100; /* default values, should */ + usbvision->i2c_adap.retries = 3; /* be replaced by defines */ + + i2c_add_adapter(&usbvision->i2c_adap); + + PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name); + /* Request the load of the i2c modules we need */ switch (usbvision_device_data[usbvision->DevModel].Codec) { case CODEC_SAA7113: - request_module("saa7115"); - break; case CODEC_SAA7111: - request_module("saa7115"); + v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "saa7115", + "saa7115_auto", saa711x_addrs); break; } if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { - request_module("tuner"); + struct v4l2_subdev *sd; + enum v4l2_i2c_tuner_type type; + struct tuner_setup tun_setup; + + sd = v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + /* depending on whether we found a demod or not, select + the tuner type. */ + type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + sd = v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + + if (usbvision->tuner_type != -1) { + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; + tun_setup.type = usbvision->tuner_type; + tun_setup.addr = v4l2_i2c_subdev_addr(sd); + call_all(usbvision, tuner, s_type_addr, &tun_setup); + } } -#endif - return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap); + return 0; } int usbvision_i2c_unregister(struct usb_usbvision *usbvision) @@ -284,67 +290,6 @@ int usbvision_i2c_unregister(struct usb_usbvision *usbvision) return 0; } -void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, - void *arg) -{ - i2c_clients_command(&usbvision->i2c_adap, cmd, arg); -} - -static int attach_inform(struct i2c_client *client) -{ - struct usb_usbvision *usbvision; - - usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); - - switch (client->addr << 1) { - case 0x42 << 1: - case 0x43 << 1: - case 0x4a << 1: - case 0x4b << 1: - PDEBUG(DBG_I2C,"attach_inform: tda9887 detected."); - break; - case 0x42: - PDEBUG(DBG_I2C,"attach_inform: saa7114 detected."); - break; - case 0x4a: - PDEBUG(DBG_I2C,"attach_inform: saa7113 detected."); - break; - case 0x48: - PDEBUG(DBG_I2C,"attach_inform: saa7111 detected."); - break; - case 0xa0: - PDEBUG(DBG_I2C,"attach_inform: eeprom detected."); - break; - - default: - { - struct tuner_setup tun_setup; - - PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1); - usbvision->tuner_addr = client->addr; - - if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) { - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = usbvision->tuner_type; - tun_setup.addr = usbvision->tuner_addr; - call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); - } - } - break; - } - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct usb_usbvision *usbvision; - - usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); - - PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name); - return 0; -} - static int usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len) @@ -517,14 +462,6 @@ static int usbvision_i2c_read(struct usb_usbvision *usbvision, unsigned char add static struct i2c_adapter i2c_adap_template = { .owner = THIS_MODULE, .name = "usbvision", - .id = I2C_HW_B_BT848, /* FIXME */ - .client_register = attach_inform, - .client_unregister = detach_inform, - .class = I2C_CLASS_TV_ANALOG, -}; - -static struct i2c_client i2c_client_template = { - .name = "usbvision internal", }; /* diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 334c77d91..cfa184d63 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -212,7 +212,7 @@ static ssize_t show_hue(struct device *cd, ctrl.id = V4L2_CID_HUE; ctrl.value = 0; if(usbvision->user) - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); + call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); @@ -227,7 +227,7 @@ static ssize_t show_contrast(struct device *cd, ctrl.id = V4L2_CID_CONTRAST; ctrl.value = 0; if(usbvision->user) - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); + call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); @@ -242,7 +242,7 @@ static ssize_t show_brightness(struct device *cd, ctrl.id = V4L2_CID_BRIGHTNESS; ctrl.value = 0; if(usbvision->user) - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); + call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); @@ -257,7 +257,7 @@ static ssize_t show_saturation(struct device *cd, ctrl.id = V4L2_CID_SATURATION; ctrl.value = 0; if(usbvision->user) - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); + call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); @@ -622,8 +622,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) usbvision->tvnormId=*id; mutex_lock(&usbvision->lock); - call_i2c_clients(usbvision, VIDIOC_S_STD, - &usbvision->tvnormId); + call_all(usbvision, tuner, s_std, usbvision->tvnormId); mutex_unlock(&usbvision->lock); /* propagate the change to the decoder */ usbvision_muxsel(usbvision, usbvision->ctl_input); @@ -645,7 +644,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, strcpy(vt->name, "Television"); } /* Let clients fill in the remainder of this struct */ - call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); + call_all(usbvision, tuner, g_tuner, vt); return 0; } @@ -659,7 +658,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, if (!usbvision->have_tuner || vt->index) return -EINVAL; /* let clients handle this */ - call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); + call_all(usbvision, tuner, s_tuner, vt); return 0; } @@ -690,7 +689,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, return -EINVAL; usbvision->freq = freq->frequency; - call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, freq); + call_all(usbvision, tuner, s_frequency, freq); return 0; } @@ -728,7 +727,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, memset(ctrl,0,sizeof(*ctrl)); ctrl->id=id; - call_i2c_clients(usbvision, VIDIOC_QUERYCTRL, ctrl); + call_all(usbvision, core, queryctrl, ctrl); if (!ctrl->type) return -EINVAL; @@ -740,7 +739,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); + call_all(usbvision, core, g_ctrl, ctrl); return 0; } @@ -749,7 +748,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); + call_all(usbvision, core, s_ctrl, ctrl); return 0; } @@ -900,10 +899,9 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct usb_usbvision *usbvision = video_drvdata(file); - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; usbvision->streaming = Stream_On; - call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); + call_all(usbvision, video, s_stream, 1); return 0; } @@ -912,7 +910,6 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { struct usb_usbvision *usbvision = video_drvdata(file); - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -920,7 +917,7 @@ static int vidioc_streamoff(struct file *file, if(usbvision->streaming == Stream_On) { usbvision_stream_interrupt(usbvision); /* Stop all video streamings */ - call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); + call_all(usbvision, video, s_stream, 0); } usbvision_empty_framequeues(usbvision); @@ -1043,7 +1040,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, if(usbvision->streaming != Stream_On) { /* no stream is running, make it running ! */ usbvision->streaming = Stream_On; - call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); + call_all(usbvision, video, s_stream, 1); } /* Then, enqueue as many frames as possible @@ -1214,7 +1211,7 @@ static int usbvision_radio_open(struct file *file) // If so far no errors then we shall start the radio usbvision->radio = 1; - call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); + call_all(usbvision, tuner, s_radio); usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); usbvision->user++; } @@ -1427,7 +1424,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, } *vdev = *vdev_template; // vdev->minor = -1; - vdev->parent = &usb_dev->dev; + vdev->v4l2_dev = &usbvision->v4l2_dev; snprintf(vdev->name, sizeof(vdev->name), "%s", name); video_set_drvdata(vdev, usbvision); return vdev; @@ -1548,33 +1545,30 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) { struct usb_usbvision *usbvision; - if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == - NULL) { - goto err_exit; - } + usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL); + if (usbvision == NULL) + return NULL; usbvision->dev = dev; + if (v4l2_device_register(&dev->dev, &usbvision->v4l2_dev)) + goto err_free; mutex_init(&usbvision->lock); /* available */ // prepare control urb for control messages during interrupts usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); - if (usbvision->ctrlUrb == NULL) { - goto err_exit; - } + if (usbvision->ctrlUrb == NULL) + goto err_unreg; init_waitqueue_head(&usbvision->ctrlUrb_wq); usbvision_init_powerOffTimer(usbvision); return usbvision; -err_exit: - if (usbvision && usbvision->ctrlUrb) { - usb_free_urb(usbvision->ctrlUrb); - } - if (usbvision) { - kfree(usbvision); - } +err_unreg: + v4l2_device_unregister(&usbvision->v4l2_dev); +err_free: + kfree(usbvision); return NULL; } @@ -1604,6 +1598,7 @@ static void usbvision_release(struct usb_usbvision *usbvision) usb_free_urb(usbvision->ctrlUrb); } + v4l2_device_unregister(&usbvision->v4l2_dev); kfree(usbvision); PDEBUG(DBG_PROBE, "success"); @@ -1739,8 +1734,6 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->tuner_type = usbvision_device_data[model].TunerType; } - usbvision->tuner_addr = ADDR_UNSET; - usbvision->DevModel = model; usbvision->remove_pending = 0; usbvision->iface = ifnum; diff --git a/linux/drivers/media/video/usbvision/usbvision.h b/linux/drivers/media/video/usbvision/usbvision.h index 590ff1e19..dc86c2139 100644 --- a/linux/drivers/media/video/usbvision/usbvision.h +++ b/linux/drivers/media/video/usbvision/usbvision.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -358,13 +358,13 @@ extern struct usbvision_device_data_st usbvision_device_data[]; extern struct usb_device_id usbvision_table[]; struct usb_usbvision { + struct v4l2_device v4l2_dev; struct video_device *vdev; /* Video Device */ struct video_device *rdev; /* Radio Device */ struct video_device *vbi; /* VBI Device */ /* i2c Declaration Section*/ struct i2c_adapter i2c_adap; - struct i2c_client i2c_client; struct urb *ctrlUrb; unsigned char ctrlUrbBuffer[8]; @@ -375,7 +375,6 @@ struct usb_usbvision { /* configuration part */ int have_tuner; int tuner_type; - int tuner_addr; int bridgeType; // NT1003, NT1004, NT1005 int radio; int video_inputs; // # of inputs @@ -465,6 +464,8 @@ struct usb_usbvision { int ComprBlockTypes[4]; }; +#define call_all(usbvision, o, f, args...) \ + v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args) /* --------------------------------------------------------------- */ /* defined in usbvision-i2c.c */ @@ -476,7 +477,6 @@ struct usb_usbvision { /* ----------------------------------------------------------------------- */ int usbvision_i2c_register(struct usb_usbvision *usbvision); int usbvision_i2c_unregister(struct usb_usbvision *usbvision); -void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); /* defined in usbvision-core.c */ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); -- cgit v1.2.3 From ceb38ab7b287651e30d049e86e6469d4bcc3ea3b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 21 Feb 2009 22:47:24 +0100 Subject: v4l2-common: remove v4l2_ctrl_query_fill_std From: Hans Verkuil The v4l2_ctrl_query_fill_std() function wasn't one the best idea I ever had. It doesn't add anything valuable that cannot be expressed equally well with v4l2_ctrl_query_fill and only adds overhead. Replace it with v4l2_ctrl_query_fill() everywhere it is used and remove it from v4l2_common.c. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx18/cx18-av-core.c | 7 +- linux/drivers/media/video/cx2341x.c | 108 ++++++++++++---- linux/drivers/media/video/cx25840/cx25840-core.c | 7 +- linux/drivers/media/video/msp3400-driver.c | 26 ++-- linux/drivers/media/video/saa7115.c | 4 +- linux/drivers/media/video/saa7134/saa6752hs.c | 12 +- .../drivers/media/video/saa7134/saa7134-empress.c | 2 +- linux/drivers/media/video/tda7432.c | 6 +- linux/drivers/media/video/tda9875.c | 3 +- linux/drivers/media/video/tvaudio.c | 17 ++- linux/drivers/media/video/tvp514x.c | 5 +- linux/drivers/media/video/v4l2-common.c | 142 --------------------- 12 files changed, 141 insertions(+), 198 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index a3bd2c95f..fc576cf1a 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -788,10 +788,12 @@ int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg) switch (qc->id) { case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); default: break; } @@ -801,10 +803,11 @@ int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg) return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, state->default_volume); case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); default: return -EINVAL; } diff --git a/linux/drivers/media/video/cx2341x.c b/linux/drivers/media/video/cx2341x.c index 01c4d2d02..2cf0c5fee 100644 --- a/linux/drivers/media/video/cx2341x.c +++ b/linux/drivers/media/video/cx2341x.c @@ -501,6 +501,29 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, int err; switch (qctrl->id) { + case V4L2_CID_MPEG_STREAM_TYPE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS, + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS); + + case V4L2_CID_MPEG_STREAM_VBI_FMT: + if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI) + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_VBI_FMT_NONE, + V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1, + V4L2_MPEG_STREAM_VBI_FMT_NONE); + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_VBI_FMT_NONE, + V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, + default_params.stream_vbi_fmt); + + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); + case V4L2_CID_MPEG_AUDIO_ENCODING: if (params->capabilities & CX2341X_CAP_HAS_AC3) { /* @@ -532,9 +555,36 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; return 0; - case V4L2_CID_MPEG_AUDIO_L1_BITRATE: - case V4L2_CID_MPEG_AUDIO_L3_BITRATE: - return -EINVAL; + case V4L2_CID_MPEG_AUDIO_MODE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_MODE_STEREO, + V4L2_MPEG_AUDIO_MODE_MONO, 1, + V4L2_MPEG_AUDIO_MODE_STEREO); + + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + err = v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); + if (err == 0 && + params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_EMPHASIS_NONE, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1, + V4L2_MPEG_AUDIO_EMPHASIS_NONE); + + case V4L2_CID_MPEG_AUDIO_CRC: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_CRC_NONE, + V4L2_MPEG_AUDIO_CRC_CRC16, 1, + V4L2_MPEG_AUDIO_CRC_NONE); + + case V4L2_CID_MPEG_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: err = v4l2_ctrl_query_fill(qctrl, @@ -551,13 +601,6 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; return 0; - case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: - err = v4l2_ctrl_query_fill_std(qctrl); - if (err == 0 && - params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) - qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; - return err; - case V4L2_CID_MPEG_VIDEO_ENCODING: /* this setting is read-only for the cx2341x since the V4L2_CID_MPEG_STREAM_TYPE really determines the @@ -570,32 +613,51 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; return err; + case V4L2_CID_MPEG_VIDEO_ASPECT: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_ASPECT_1x1, + V4L2_MPEG_VIDEO_ASPECT_221x100, 1, + V4L2_MPEG_VIDEO_ASPECT_4x3); + + case V4L2_CID_MPEG_VIDEO_B_FRAMES: + return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2); + + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, + params->is_50hz ? 12 : 15); + + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; return err; + case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; return err; - case V4L2_CID_MPEG_STREAM_VBI_FMT: - if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI) - return v4l2_ctrl_query_fill_std(qctrl); - return cx2341x_ctrl_query_fill(qctrl, - V4L2_MPEG_STREAM_VBI_FMT_NONE, - V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, - default_params.stream_vbi_fmt); + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: + return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, - params->is_50hz ? 12 : 15); + case V4L2_CID_MPEG_VIDEO_MUTE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); + + case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */ + return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080); /* CX23415/6 specific */ case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: @@ -697,7 +759,7 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, default_params.stream_insert_nav_packets); default: - return v4l2_ctrl_query_fill_std(qctrl); + return -EINVAL; } } diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index d70dcd028..921cc96fc 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -1224,10 +1224,12 @@ static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) switch (qc->id) { case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); default: break; } @@ -1239,10 +1241,11 @@ static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, state->default_volume); case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); default: return -EINVAL; } diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index 053f168bf..61b54317f 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -718,22 +718,24 @@ static int msp_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) struct msp_state *state = to_state(sd); switch (qc->id) { - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill_std(qc); - default: - break; + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + default: + break; } if (!state->has_sound_processing) return -EINVAL; switch (qc->id) { - case V4L2_CID_AUDIO_LOUDNESS: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); - default: - return -EINVAL; + case V4L2_CID_AUDIO_LOUDNESS: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); + default: + return -EINVAL; } return 0; } diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 9fbb93775..a870ae5d2 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1207,10 +1207,12 @@ static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { switch (qc->id) { case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); default: return -EINVAL; } diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index 2e2871de1..3af36d929 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -599,7 +599,7 @@ static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc V4L2_MPEG_VIDEO_ASPECT_4x3); case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); if (err == 0 && params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) @@ -613,12 +613,20 @@ static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc V4L2_MPEG_STREAM_TYPE_MPEG2_TS); case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); case V4L2_CID_MPEG_STREAM_PID_PMT: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); case V4L2_CID_MPEG_STREAM_PID_AUDIO: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); case V4L2_CID_MPEG_STREAM_PID_VIDEO: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); case V4L2_CID_MPEG_STREAM_PID_PCR: - return v4l2_ctrl_query_fill_std(qctrl); + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); default: break; diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index 813f5f88d..609342128 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -390,7 +390,7 @@ static int empress_queryctrl(struct file *file, void *priv, if (c->id == 0) return -EINVAL; if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS) - return v4l2_ctrl_query_fill_std(c); + return v4l2_ctrl_query_fill(c, 0, 0, 0, 0); if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG) return saa7134_queryctrl(file, priv, c); return saa_call_empress(dev, core, queryctrl, c); diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 30f6f8a38..104fc4246 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -422,12 +422,14 @@ static int tda7432_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); } return -EINVAL; } diff --git a/linux/drivers/media/video/tda9875.c b/linux/drivers/media/video/tda9875.c index 892d25a40..938bafbbd 100644 --- a/linux/drivers/media/video/tda9875.c +++ b/linux/drivers/media/video/tda9875.c @@ -327,9 +327,10 @@ static int tda9875_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { switch (qc->id) { case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); } return -EINVAL; } diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 3ca242af5..e8a6893ff 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -1644,21 +1644,24 @@ static int tvaudio_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) switch (qc->id) { case V4L2_CID_AUDIO_MUTE: - break; + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUDIO_VOLUME: + if (desc->flags & CHIP_HAS_VOLUME) + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); + break; case V4L2_CID_AUDIO_BALANCE: - if (!(desc->flags & CHIP_HAS_VOLUME)) - return -EINVAL; + if (desc->flags & CHIP_HAS_VOLUME) + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); break; case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - if (!(desc->flags & CHIP_HAS_BASSTREBLE)) - return -EINVAL; + if (desc->flags & CHIP_HAS_BASSTREBLE) + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); break; default: - return -EINVAL; + break; } - return v4l2_ctrl_query_fill_std(qc); + return -EINVAL; } static int tvaudio_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *rt) diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c index 5f4cbc2b2..c20af91ff 100644 --- a/linux/drivers/media/video/tvp514x.c +++ b/linux/drivers/media/video/tvp514x.c @@ -719,10 +719,9 @@ ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qctrl) switch (qctrl->id) { case V4L2_CID_BRIGHTNESS: - /* Brightness supported is same as standard one (0-255), - * so make use of standard API provided. + /* Brightness supported is (0-255), */ - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); break; case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 8ae8dd366..963277e93 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -561,148 +561,6 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste } EXPORT_SYMBOL(v4l2_ctrl_query_fill); -/* Fill in a struct v4l2_queryctrl with standard values based on - the control ID. */ -int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) -{ - switch (qctrl->id) { - /* USER controls */ - case V4L2_CID_USER_CLASS: - case V4L2_CID_MPEG_CLASS: - return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880); - case V4L2_CID_AUDIO_MUTE: - case V4L2_CID_AUDIO_LOUDNESS: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 32768); - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0); - - /* MPEG controls */ - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); - case V4L2_CID_MPEG_AUDIO_ENCODING: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_ENCODING_LAYER_1, - V4L2_MPEG_AUDIO_ENCODING_AC3, 1, - V4L2_MPEG_AUDIO_ENCODING_LAYER_2); - case V4L2_CID_MPEG_AUDIO_L1_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_L1_BITRATE_32K, - V4L2_MPEG_AUDIO_L1_BITRATE_448K, 1, - V4L2_MPEG_AUDIO_L1_BITRATE_256K); - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_L2_BITRATE_32K, - V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, - V4L2_MPEG_AUDIO_L2_BITRATE_224K); - case V4L2_CID_MPEG_AUDIO_L3_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_L3_BITRATE_32K, - V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, - V4L2_MPEG_AUDIO_L3_BITRATE_192K); - case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: - return v4l2_ctrl_query_fill(qctrl, 0, 6400, 1, 3200000); - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_AC3_BITRATE_32K, - V4L2_MPEG_AUDIO_AC3_BITRATE_640K, 1, - V4L2_MPEG_AUDIO_AC3_BITRATE_384K); - case V4L2_CID_MPEG_AUDIO_MODE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_MODE_STEREO, - V4L2_MPEG_AUDIO_MODE_MONO, 1, - V4L2_MPEG_AUDIO_MODE_STEREO); - case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); - case V4L2_CID_MPEG_AUDIO_EMPHASIS: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_EMPHASIS_NONE, - V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1, - V4L2_MPEG_AUDIO_EMPHASIS_NONE); - case V4L2_CID_MPEG_AUDIO_CRC: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_CRC_NONE, - V4L2_MPEG_AUDIO_CRC_CRC16, 1, - V4L2_MPEG_AUDIO_CRC_NONE); - case V4L2_CID_MPEG_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - case V4L2_CID_MPEG_VIDEO_ENCODING: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_ENCODING_MPEG_1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2); - case V4L2_CID_MPEG_VIDEO_ASPECT: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_ASPECT_1x1, - V4L2_MPEG_VIDEO_ASPECT_221x100, 1, - V4L2_MPEG_VIDEO_ASPECT_4x3); - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2); - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 12); - case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); - case V4L2_CID_MPEG_VIDEO_PULLDOWN: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); - case V4L2_CID_MPEG_VIDEO_BITRATE: - return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); - case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: - return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); - case V4L2_CID_MPEG_VIDEO_MUTE: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */ - return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080); - case V4L2_CID_MPEG_STREAM_TYPE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_STREAM_TYPE_MPEG2_PS, - V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1, - V4L2_MPEG_STREAM_TYPE_MPEG2_PS); - case V4L2_CID_MPEG_STREAM_PID_PMT: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); - case V4L2_CID_MPEG_STREAM_PID_AUDIO: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); - case V4L2_CID_MPEG_STREAM_PID_VIDEO: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); - case V4L2_CID_MPEG_STREAM_PID_PCR: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); - case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: - return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); - case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: - return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); - case V4L2_CID_MPEG_STREAM_VBI_FMT: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_STREAM_VBI_FMT_NONE, - V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1, - V4L2_MPEG_STREAM_VBI_FMT_NONE); - default: - return -EINVAL; - } -} -EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); - /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and the menu. The qctrl pointer may be NULL, in which case it is ignored. If menu_items is NULL, then the menu items are retrieved using -- cgit v1.2.3 From 7613bd8a3cc9cb591a3edcbce872d2e8f90d7bb6 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Mon, 23 Feb 2009 10:27:16 +0100 Subject: [PATCH] software IRQ watchdog for Flexcop B2C2 DVB PCI cards From: Patrick Boettcher With (some) Technisat cards you cannot run multiple DVB applications in parallel and switch the channel at the same time. There seems to be a problem on the interfaces or even inside the flexcop-device that can't handle interruption on the streaming interface. This patch adds a watchdog to check whether data is supposed to come in (streaming PIDs are requested) and if no data is seen within 400ms (default) it resets the streaming/pid-filtering hardware. This patch is urgently needed to support the rev 2.8 of the hardware and solves problem occassionally seen on older hardware. Priority: high Signed-off-by: Uwe Bugla Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c | 1 + linux/drivers/media/dvb/b2c2/flexcop-pci.c | 75 +++++++++++++++++------- linux/drivers/media/dvb/b2c2/flexcop.c | 3 +- 3 files changed, 55 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c index b386cc66c..451974ba3 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c @@ -192,6 +192,7 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d return 0; } +EXPORT_SYMBOL(flexcop_pid_feed_control); void flexcop_hw_filter_init(struct flexcop_device *fc) { diff --git a/linux/drivers/media/dvb/b2c2/flexcop-pci.c b/linux/drivers/media/dvb/b2c2/flexcop-pci.c index 853a3ccff..5baf9ded9 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-pci.c @@ -13,9 +13,9 @@ static int enable_pid_filtering = 1; module_param(enable_pid_filtering, int, 0444); MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); -static int irq_chk_intv; +static int irq_chk_intv = 100; module_param(irq_chk_intv, int, 0644); -MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging)."); +MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog."); #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG #define dprintk(level,args...) \ @@ -34,7 +34,9 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); +MODULE_PARM_DESC(debug, + "set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))." + DEBSTATUS); #define DRIVER_VERSION "0.1" #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" @@ -58,6 +60,8 @@ struct flexcop_pci { int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ int count; + int count_prev; + int stream_problem; spinlock_t irq_lock; @@ -115,18 +119,44 @@ static void flexcop_pci_irq_check_work(struct work_struct *work) #endif struct flexcop_device *fc = fc_pci->fc_dev; - flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); - - flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4); + if (fc->feedcount) { +#if 0 + flexcop_ibi_value v = fc->read_ibi_reg(fc, sram_dest_reg_714); + deb_chk("net_ovflow_error: %d, media_ovflow_error: %d," + "cai_ovflow_error: %d, cao_ovflow_error: %d, " + "sram_dma: %d, maximumfill: %d\n", + v.sram_dest_reg_714.net_ovflow_error, + v.sram_dest_reg_714.media_ovflow_error, + v.sram_dest_reg_714.cai_ovflow_error, + v.sram_dest_reg_714.cao_ovflow_error, + v.sram_dest_reg_714.ctrl_sramdma, + v.sram_dest_reg_714.ctrl_maximumfill); +#endif - if (v.sram_dest_reg_714.net_ovflow_error) - deb_chk("sram net_ovflow_error\n"); - if (v.sram_dest_reg_714.media_ovflow_error) - deb_chk("sram media_ovflow_error\n"); - if (v.sram_dest_reg_714.cai_ovflow_error) - deb_chk("sram cai_ovflow_error\n"); - if (v.sram_dest_reg_714.cai_ovflow_error) - deb_chk("sram cai_ovflow_error\n"); + if (fc_pci->count == fc_pci->count_prev) { + deb_chk("no IRQ since the last check\n"); + if (fc_pci->stream_problem++ == 3) { + struct dvb_demux_feed *feed; + + spin_lock_irq(&fc->demux.lock); + list_for_each_entry(feed, &fc->demux.feed_list, + list_head) { + flexcop_pid_feed_control(fc, feed, 0); + } + + list_for_each_entry(feed, &fc->demux.feed_list, + list_head) { + flexcop_pid_feed_control(fc, feed, 1); + } + spin_unlock_irq(&fc->demux.lock); + + fc_pci->stream_problem = 0; + } + } else { + fc_pci->stream_problem = 0; + fc_pci->count_prev = fc_pci->count; + } + } schedule_delayed_work(&fc_pci->irq_check_work, msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); @@ -232,16 +262,12 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff) flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); deb_irq("IRQ enabled\n"); + fc_pci->count_prev = fc_pci->count; + // fc_pci->active_dma1_addr = 0; // flexcop_dma_control_size_irq(fc,FC_DMA_1,1); - if (irq_chk_intv > 0) - schedule_delayed_work(&fc_pci->irq_check_work, - msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); } else { - if (irq_chk_intv > 0) - cancel_delayed_work(&fc_pci->irq_check_work); - flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); deb_irq("IRQ disabled\n"); @@ -315,8 +341,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) goto err_pci_iounmap; - - fc_pci->init_state |= FC_PCI_INIT; return ret; @@ -395,6 +419,10 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); #endif + if (irq_chk_intv > 0) + schedule_delayed_work(&fc_pci->irq_check_work, + msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); + return ret; err_fc_exit: @@ -413,6 +441,9 @@ static void flexcop_pci_remove(struct pci_dev *pdev) { struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); + if (irq_chk_intv > 0) + cancel_delayed_work(&fc_pci->irq_check_work); + flexcop_pci_dma_exit(fc_pci); flexcop_device_exit(fc_pci->fc_dev); flexcop_pci_exit(fc_pci); diff --git a/linux/drivers/media/dvb/b2c2/flexcop.c b/linux/drivers/media/dvb/b2c2/flexcop.c index 676413a91..91068952b 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop.c +++ b/linux/drivers/media/dvb/b2c2/flexcop.c @@ -212,8 +212,7 @@ void flexcop_reset_block_300(struct flexcop_device *fc) v210.sw_reset_210.Block_reset_enable = 0xb2; fc->write_ibi_reg(fc,sw_reset_210,v210); - msleep(1); - + udelay(1000); fc->write_ibi_reg(fc,ctrl_208,v208_save); } -- cgit v1.2.3 From 9fff09d63089bb9963bac49d563e934a54d2ccb6 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:12:58 +0100 Subject: soc-camera: add data signal polarity flags to drivers From: Guennadi Liakhovetski All soc-camera camera and host drivers must specify supported data signal polarity, after all drivers are fixed, we'll add a suitable test to soc_camera_bus_param_compatible(). Signed-off-by: Guennadi Liakhovetski --- arch/sh/boards/board-ap325rxa.c | 3 ++- arch/sh/boards/mach-migor/setup.c | 5 +++-- drivers/media/video/mt9m001.c | 2 +- drivers/media/video/mt9m111.c | 2 +- drivers/media/video/mt9v022.c | 2 +- drivers/media/video/ov772x.c | 2 +- drivers/media/video/pxa_camera.c | 1 + 7 files changed, 10 insertions(+), 7 deletions(-) --- linux/drivers/media/video/mt9m001.c | 2 +- linux/drivers/media/video/mt9m111.c | 2 +- linux/drivers/media/video/mt9v022.c | 2 +- linux/drivers/media/video/ov772x.c | 2 +- linux/drivers/media/video/pxa_camera.c | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 3d8e6ed8d..c2e52100a 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -276,7 +276,7 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) /* MT9M001 has all capture_format parameters fixed */ unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | - SOCAM_MASTER; + SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER; if (bus_switch_possible(mt9m001)) flags |= SOCAM_DATAWIDTH_8; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index cdf3f38e2..b2989c0f2 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -420,7 +420,7 @@ static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) struct soc_camera_link *icl = mt9m111->client->dev.platform_data; unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | - SOCAM_DATAWIDTH_8; + SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; return soc_camera_apply_sensor_flags(icl, flags); } diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 9601884ca..59efb8ff0 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -336,7 +336,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | - SOCAM_MASTER | SOCAM_SLAVE | + SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_SLAVE | width_flag; } diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index ce389cacf..74458378a 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -718,7 +718,7 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) struct soc_camera_link *icl = priv->client->dev.platform_data; unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | - priv->info->buswidth; + SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; return soc_camera_apply_sensor_flags(icl, flags); } diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index b6a34ba18..dd524b3c6 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -888,6 +888,7 @@ static int test_platform_param(struct pxa_camera_dev *pcdev, SOCAM_HSYNC_ACTIVE_LOW | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_DATA_ACTIVE_HIGH | SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING; -- cgit v1.2.3 From 20489b399dff421863ee89585f32b960bf7b420e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:12:58 +0100 Subject: ov772x: move configuration from start_capture() to set_fmt() From: Kuninori Morimoto soc_camera framework requires, that camera configuration is performed in set_fmt, and start_capture and stop_capture only turn the camera on/off. This patch modifies ov772x to comply to this requirement. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 125 +++++++++++++++++++++--------------------- 1 files changed, 62 insertions(+), 63 deletions(-) --- linux/drivers/media/video/ov772x.c | 125 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 63 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 74458378a..881463a0b 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -500,9 +500,8 @@ static const struct soc_camera_data_format ov772x_fmt_lists[] = { /* * color format list */ -#define T_YUYV 0 static const struct ov772x_color_format ov772x_cfmts[] = { - [T_YUYV] = { + { SETFOURCC(YUYV), .regs = ov772x_YYUV_regs, }, @@ -635,74 +634,20 @@ static int ov772x_release(struct soc_camera_device *icd) static int ov772x_start_capture(struct soc_camera_device *icd) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - int ret; - - if (!priv->win) - priv->win = &ov772x_win_vga; - if (!priv->fmt) - priv->fmt = &ov772x_cfmts[T_YUYV]; - - /* - * reset hardware - */ - ov772x_reset(priv->client); - - /* - * set color format - */ - ret = ov772x_write_array(priv->client, priv->fmt->regs); - if (ret < 0) - goto start_end; - - /* - * set size format - */ - ret = ov772x_write_array(priv->client, priv->win->regs); - if (ret < 0) - goto start_end; - - /* - * set COM7 bit ( QVGA or VGA ) - */ - ret = ov772x_mask_set(priv->client, - COM7, SLCT_MASK, priv->win->com7_bit); - if (ret < 0) - goto start_end; - /* - * set UV setting - */ - if (priv->fmt->option & OP_UV) { - ret = ov772x_mask_set(priv->client, - DSP_CTRL3, UV_MASK, UV_ON); - if (ret < 0) - goto start_end; - } - - /* - * set SWAP setting - */ - if (priv->fmt->option & OP_SWAP_RGB) { - ret = ov772x_mask_set(priv->client, - COM3, SWAP_MASK, SWAP_RGB); - if (ret < 0) - goto start_end; + if (!priv->win || !priv->fmt) { + dev_err(&icd->dev, "norm or win select error\n"); + return -EPERM; } dev_dbg(&icd->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); -start_end: - priv->fmt = NULL; - priv->win = NULL; - - return ret; + return 0; } static int ov772x_stop_capture(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - ov772x_reset(priv->client); return 0; } @@ -787,7 +732,6 @@ ov772x_select_win(u32 width, u32 height) return win; } - static int ov772x_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) @@ -803,16 +747,72 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { if (pixfmt == ov772x_cfmts[i].fourcc) { priv->fmt = ov772x_cfmts + i; - ret = 0; break; } } + if (!priv->fmt) + goto ov772x_set_fmt_error; /* * select win */ priv->win = ov772x_select_win(rect->width, rect->height); + /* + * reset hardware + */ + ov772x_reset(priv->client); + + /* + * set color format + */ + ret = ov772x_write_array(priv->client, priv->fmt->regs); + if (ret < 0) + goto ov772x_set_fmt_error; + + /* + * set size format + */ + ret = ov772x_write_array(priv->client, priv->win->regs); + if (ret < 0) + goto ov772x_set_fmt_error; + + /* + * set COM7 bit ( QVGA or VGA ) + */ + ret = ov772x_mask_set(priv->client, + COM7, SLCT_MASK, priv->win->com7_bit); + if (ret < 0) + goto ov772x_set_fmt_error; + + /* + * set UV setting + */ + if (priv->fmt->option & OP_UV) { + ret = ov772x_mask_set(priv->client, + DSP_CTRL3, UV_MASK, UV_ON); + if (ret < 0) + goto ov772x_set_fmt_error; + } + + /* + * set SWAP setting + */ + if (priv->fmt->option & OP_SWAP_RGB) { + ret = ov772x_mask_set(priv->client, + COM3, SWAP_MASK, SWAP_RGB); + if (ret < 0) + goto ov772x_set_fmt_error; + } + + return ret; + +ov772x_set_fmt_error: + + ov772x_reset(priv->client); + priv->win = NULL; + priv->fmt = NULL; + return ret; } @@ -889,7 +889,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd) i2c_smbus_read_byte_data(priv->client, MIDH), i2c_smbus_read_byte_data(priv->client, MIDL)); - return soc_camera_video_start(icd); } -- cgit v1.2.3 From 7c67818bb02d27076080edb44bbcb661e45fd2a5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:12:58 +0100 Subject: ov772x: setting method to register is changed. From: Kuninori Morimoto Color format regs array had been used, but it was not easy to understand what to want to do, and additional bit became complex. This patch modify this problem. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 121 +++++++++++++++++------------------------- 1 files changed, 48 insertions(+), 73 deletions(-) --- linux/drivers/media/video/ov772x.c | 121 +++++++++++++++---------------------- 1 file changed, 48 insertions(+), 73 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 881463a0b..211376a41 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -271,11 +271,13 @@ #define SLCT_QVGA 0x40 /* 1 : QVGA */ #define ITU656_ON_OFF 0x20 /* ITU656 protocol ON/OFF selection */ /* RGB output format control */ +#define FMT_MASK 0x0c /* Mask of color format */ #define FMT_GBR422 0x00 /* 00 : GBR 4:2:2 */ #define FMT_RGB565 0x04 /* 01 : RGB 565 */ #define FMT_RGB555 0x08 /* 10 : RGB 555 */ #define FMT_RGB444 0x0c /* 11 : RGB 444 */ /* Output format control */ +#define OFMT_MASK 0x03 /* Mask of output format */ #define OFMT_YUV 0x00 /* 00 : YUV */ #define OFMT_P_BRAW 0x01 /* 01 : Processed Bayer RAW */ #define OFMT_RGB 0x02 /* 10 : RGB */ @@ -299,7 +301,7 @@ #define GAIN_2x 0x00 /* 000 : 2x */ #define GAIN_4x 0x10 /* 001 : 4x */ #define GAIN_8x 0x20 /* 010 : 8x */ -#define GAIN_16x 0x30 /* 011 : 16x */ +#define GAIN_16x 0x30 /* 011 : 16x */ #define GAIN_32x 0x40 /* 100 : 32x */ #define GAIN_64x 0x50 /* 101 : 64x */ #define GAIN_128x 0x60 /* 110 : 128x */ @@ -355,13 +357,6 @@ #define VOSZ_VGA 0xF0 #define VOSZ_QVGA 0x78 -/* - * bit configure (32 bit) - * this is used in struct ov772x_color_format :: option - */ -#define OP_UV 0x00000001 -#define OP_SWAP_RGB 0x00000002 - /* * ID */ @@ -380,8 +375,9 @@ struct regval_list { struct ov772x_color_format { char *name; __u32 fourcc; - const struct regval_list *regs; - unsigned int option; + u8 dsp3; + u8 com3; + u8 com7; }; struct ov772x_win_size { @@ -403,34 +399,6 @@ struct ov772x_priv { #define ENDMARKER { 0xff, 0xff } -/* - * register setting for color format - */ -static const struct regval_list ov772x_RGB555_regs[] = { - { COM3, 0x00 }, - { COM7, FMT_RGB555 | OFMT_RGB }, - ENDMARKER, -}; - -static const struct regval_list ov772x_RGB565_regs[] = { - { COM3, 0x00 }, - { COM7, FMT_RGB565 | OFMT_RGB }, - ENDMARKER, -}; - -static const struct regval_list ov772x_YYUV_regs[] = { - { COM3, SWAP_YUV }, - { COM7, OFMT_YUV }, - ENDMARKER, -}; - -static const struct regval_list ov772x_UVYY_regs[] = { - { COM3, 0x00 }, - { COM7, OFMT_YUV }, - ENDMARKER, -}; - - /* * register setting for window size */ @@ -503,34 +471,45 @@ static const struct soc_camera_data_format ov772x_fmt_lists[] = { static const struct ov772x_color_format ov772x_cfmts[] = { { SETFOURCC(YUYV), - .regs = ov772x_YYUV_regs, + .dsp3 = 0x0, + .com3 = SWAP_YUV, + .com7 = OFMT_YUV, }, { SETFOURCC(YVYU), - .regs = ov772x_YYUV_regs, - .option = OP_UV, + .dsp3 = UV_ON, + .com3 = SWAP_YUV, + .com7 = OFMT_YUV, }, { SETFOURCC(UYVY), - .regs = ov772x_UVYY_regs, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = OFMT_YUV, }, { SETFOURCC(RGB555), - .regs = ov772x_RGB555_regs, - .option = OP_SWAP_RGB, + .dsp3 = 0x0, + .com3 = SWAP_RGB, + .com7 = FMT_RGB555 | OFMT_RGB, }, { SETFOURCC(RGB555X), - .regs = ov772x_RGB555_regs, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = FMT_RGB555 | OFMT_RGB, }, { SETFOURCC(RGB565), - .regs = ov772x_RGB565_regs, - .option = OP_SWAP_RGB, + .dsp3 = 0x0, + .com3 = SWAP_RGB, + .com7 = FMT_RGB565 | OFMT_RGB, }, { SETFOURCC(RGB565X), - .regs = ov772x_RGB565_regs, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = FMT_RGB565 | OFMT_RGB, }, }; @@ -738,6 +717,7 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); int ret = -EINVAL; + u8 val; int i; /* @@ -763,13 +743,6 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, */ ov772x_reset(priv->client); - /* - * set color format - */ - ret = ov772x_write_array(priv->client, priv->fmt->regs); - if (ret < 0) - goto ov772x_set_fmt_error; - /* * set size format */ @@ -778,32 +751,34 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, goto ov772x_set_fmt_error; /* - * set COM7 bit ( QVGA or VGA ) + * set DSP_CTRL3 */ - ret = ov772x_mask_set(priv->client, - COM7, SLCT_MASK, priv->win->com7_bit); - if (ret < 0) - goto ov772x_set_fmt_error; - - /* - * set UV setting - */ - if (priv->fmt->option & OP_UV) { + val = priv->fmt->dsp3; + if (val) { ret = ov772x_mask_set(priv->client, - DSP_CTRL3, UV_MASK, UV_ON); + DSP_CTRL3, UV_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; } /* - * set SWAP setting + * set COM3 */ - if (priv->fmt->option & OP_SWAP_RGB) { - ret = ov772x_mask_set(priv->client, - COM3, SWAP_MASK, SWAP_RGB); - if (ret < 0) - goto ov772x_set_fmt_error; - } + val = priv->fmt->com3; + ret = ov772x_mask_set(priv->client, + COM3, SWAP_MASK, val); + if (ret < 0) + goto ov772x_set_fmt_error; + + /* + * set COM7 + */ + val = priv->win->com7_bit | priv->fmt->com7; + ret = ov772x_mask_set(priv->client, + COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), + val); + if (ret < 0) + goto ov772x_set_fmt_error; return ret; -- cgit v1.2.3 From 9f4da9c7feb71ee575960553c4ad10555be64229 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:12:58 +0100 Subject: ov772x: bit mask operation fix on ov772x_mask_set. From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) --- linux/drivers/media/video/ov772x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 211376a41..6e7cfeb18 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -565,8 +565,11 @@ static int ov772x_mask_set(struct i2c_client *client, u8 set) { s32 val = i2c_smbus_read_byte_data(client, command); + if (val < 0) + return val; + val &= ~mask; - val |= set; + val |= set & mask; return i2c_smbus_write_byte_data(client, command, val); } -- cgit v1.2.3 From 7c7069267de14d7c83c611220087cdddd8210604 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:12:58 +0100 Subject: ov772x: Add image flip support From: Kuninori Morimoto o ov772x_camera_info :: flags supports default image flip. o V4L2_CID_VFLIP/HFLIP supports image flip for user side. Thank Magnus for advice. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 88 ++++++++++++++++++++++++++++++++++++++++-- include/media/ov772x.h | 5 ++ 2 files changed, 89 insertions(+), 4 deletions(-) --- linux/drivers/media/video/ov772x.c | 88 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 6e7cfeb18..2f3313524 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -217,10 +217,11 @@ #define OCAP_4x 0x03 /* 4x */ /* COM3 */ -#define SWAP_MASK 0x38 +#define SWAP_MASK (SWAP_RGB | SWAP_YUV | SWAP_ML) +#define IMG_MASK (VFLIP_IMG | HFLIP_IMG) -#define VFIMG_ON_OFF 0x80 /* Vertical flip image ON/OFF selection */ -#define HMIMG_ON_OFF 0x40 /* Horizontal mirror image ON/OFF selection */ +#define VFLIP_IMG 0x80 /* Vertical flip image ON/OFF selection */ +#define HFLIP_IMG 0x40 /* Horizontal mirror image ON/OFF selection */ #define SWAP_RGB 0x20 /* Swap B/R output sequence in RGB mode */ #define SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV mode */ #define SWAP_ML 0x08 /* Swap output MSB/LSB */ @@ -395,6 +396,8 @@ struct ov772x_priv { const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; + unsigned int flag_vflip:1; + unsigned int flag_hflip:1; }; #define ENDMARKER { 0xff, 0xff } @@ -540,6 +543,27 @@ static const struct ov772x_win_size ov772x_win_qvga = { .regs = ov772x_qvga_regs, }; +static const struct v4l2_queryctrl ov772x_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, +}; + /* * general function @@ -650,6 +674,49 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } +static int ov772x_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + ctrl->value = priv->flag_vflip; + break; + case V4L2_CID_HFLIP: + ctrl->value = priv->flag_hflip; + break; + } + return 0; +} + +static int ov772x_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + int ret = 0; + u8 val; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + val = ctrl->value ? VFLIP_IMG : 0x00; + priv->flag_vflip = ctrl->value; + if (priv->info->flags & OV772X_FLAG_VFLIP) + val ^= VFLIP_IMG; + ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); + break; + case V4L2_CID_HFLIP: + val = ctrl->value ? HFLIP_IMG : 0x00; + priv->flag_hflip = ctrl->value; + if (priv->info->flags & OV772X_FLAG_HFLIP) + val ^= HFLIP_IMG; + ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); + break; + } + + return ret; +} + static int ov772x_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { @@ -768,8 +835,17 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, * set COM3 */ val = priv->fmt->com3; + if (priv->info->flags & OV772X_FLAG_VFLIP) + val |= VFLIP_IMG; + if (priv->info->flags & OV772X_FLAG_HFLIP) + val |= HFLIP_IMG; + if (priv->flag_vflip) + val ^= VFLIP_IMG; + if (priv->flag_hflip) + val ^= HFLIP_IMG; + ret = ov772x_mask_set(priv->client, - COM3, SWAP_MASK, val); + COM3, SWAP_MASK | IMG_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -887,6 +963,10 @@ static struct soc_camera_ops ov772x_ops = { .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, + .controls = ov772x_controls, + .num_controls = ARRAY_SIZE(ov772x_controls), + .get_control = ov772x_get_control, + .set_control = ov772x_set_control, .get_chip_id = ov772x_get_chip_id, #ifdef CONFIG_VIDEO_ADV_DEBUG .get_register = ov772x_get_register, -- cgit v1.2.3 From 5f142c1dc4286e15ad35fc32896d12a4badf84b7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:12:58 +0100 Subject: tw9910: bit mask operation fix on tw9910_mask_set. From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/tw9910.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) --- linux/drivers/media/video/tw9910.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 4593cdea7..ed8dca3bf 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -460,9 +460,11 @@ static int tw9910_mask_set(struct i2c_client *client, u8 command, u8 mask, u8 set) { s32 val = i2c_smbus_read_byte_data(client, command); + if (val < 0) + return val; val &= ~mask; - val |= set; + val |= set & mask; return i2c_smbus_write_byte_data(client, command, val); } -- cgit v1.2.3 From 64c5c0e18bea0815ea7a971107b21a6c606bad77 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:12:58 +0100 Subject: sh_mobile_ceu: SOCAM flags are not platform dependent From: Kuninori Morimoto sh_mobile_ceu_camera.c support for signal polarity flags isn't platform dependent, provide them locally. Only the bus width is implementation specific. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 28 ++++++++++++++++++++++++++-- include/media/sh_mobile_ceu.h | 5 +++-- 2 files changed, 29 insertions(+), 4 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 28 ++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index ee113de47..19b04bfa4 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -102,6 +102,30 @@ struct sh_mobile_ceu_dev { const struct soc_camera_data_format *camera_fmt; }; +static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev) +{ + unsigned long flags; + + flags = SOCAM_MASTER | + SOCAM_PCLK_SAMPLE_RISING | + SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_HSYNC_ACTIVE_LOW | + SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_DATA_ACTIVE_HIGH; + + if (pcdev->pdata->flags & SH_CEU_FLAG_USE_8BIT_BUS) + flags |= SOCAM_DATAWIDTH_8; + + if (pcdev->pdata->flags & SH_CEU_FLAG_USE_16BIT_BUS) + flags |= SOCAM_DATAWIDTH_16; + + if (flags & SOCAM_DATAWIDTH_MASK) + return flags; + + return 0; +} + static void ceu_write(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs, u32 data) { @@ -397,7 +421,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, - pcdev->pdata->flags); + make_bus_param(pcdev)); if (!common_flags) return -EINVAL; @@ -518,7 +542,7 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, - pcdev->pdata->flags); + make_bus_param(pcdev)); if (!common_flags) return -EINVAL; -- cgit v1.2.3 From 426a59d72f4443f7d8cb949a514b566bc0f64cad Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:12:58 +0100 Subject: sh_mobile_ceu_camera: include NV* formats into the format list only once. From: Guennadi Liakhovetski Currently, if an soc-camera device, connected to the sh_mobile_ceu_camera camera host driver, supports several formats from the UYVY, VYUY, YUYV, YVYU set, the driver would add four NV* formats for each of them. This patch fixes this misbehaviour. Reported-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 19 +++++++++++++++++++ 1 files changed, 19 insertions(+), 0 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 19b04bfa4..29ff02802 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -587,11 +587,29 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, if (ret < 0) return 0; + /* Beginning of a pass */ + if (!idx) + icd->host_priv = NULL; + switch (icd->formats[idx].fourcc) { case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YVYU: + if (icd->host_priv) + goto add_single_format; + + /* + * Our case is simple so far: for any of the above four camera + * formats we add all our four synthesized NV* formats, so, + * just marking the device with a single flag suffices. If + * the format generation rules are more complex, you would have + * to actually hang your already added / counted formats onto + * the host_priv pointer and check whether the format you're + * going to add now is already there. + */ + icd->host_priv = (void *)sh_mobile_ceu_formats; + n = ARRAY_SIZE(sh_mobile_ceu_formats); formats += n; for (k = 0; xlate && k < n; k++) { @@ -604,6 +622,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, icd->formats[idx].name); } default: +add_single_format: /* Generic pass-through */ formats++; if (xlate) { -- cgit v1.2.3 From 353a84c516af7a6b6f293a8dc526e76b366db4ff Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:13:23 +0100 Subject: mt9t031: fix gain and hflip controls, register update, and scaling From: Guennadi Liakhovetski Multiple fixes: 1. allow register update by setting the Output Control register to 2 and not 3 2. fix scaling factor calculations 3. recover lost HFLIP control 4. fix Global Gain calculation Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9t031.c | 127 +++++++++++++++++++++++++++-------------- 1 files changed, 84 insertions(+), 43 deletions(-) --- linux/drivers/media/video/mt9t031.c | 127 ++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 43 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index dd5bd9dd0..aa0e8ec34 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -150,7 +150,7 @@ static int mt9t031_init(struct soc_camera_device *icd) if (ret >= 0) ret = reg_write(icd, MT9T031_RESET, 0); if (ret >= 0) - ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3); + ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); return ret >= 0 ? 0 : -EIO; } @@ -158,14 +158,14 @@ static int mt9t031_init(struct soc_camera_device *icd) static int mt9t031_release(struct soc_camera_device *icd) { /* Disable the chip */ - reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3); + reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); return 0; } static int mt9t031_start_capture(struct soc_camera_device *icd) { /* Switch to master "normal" mode */ - if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 3) < 0) + if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } @@ -173,7 +173,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd) static int mt9t031_stop_capture(struct soc_camera_device *icd) { /* Stop sensor readout */ - if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3) < 0) + if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } @@ -201,6 +201,18 @@ static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); } +/* Round up minima and round down maxima */ +static void recalculate_limits(struct soc_camera_device *icd, + u16 xskip, u16 yskip) +{ + icd->x_min = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; + icd->y_min = (MT9T031_ROW_SKIP + yskip - 1) / yskip; + icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip; + icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip; + icd->width_max = MT9T031_MAX_WIDTH / xskip; + icd->height_max = MT9T031_MAX_HEIGHT / yskip; +} + static int mt9t031_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { @@ -208,54 +220,70 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, int ret; const u16 hblank = MT9T031_HORIZONTAL_BLANK, vblank = MT9T031_VERTICAL_BLANK; - u16 xbin, xskip = mt9t031->xskip, ybin, yskip = mt9t031->yskip, - width = rect->width * xskip, height = rect->height * yskip; + u16 xbin, xskip, ybin, yskip, width, height, left, top; if (pixfmt) { - /* S_FMT - use binning and skipping for scaling, recalculate */ + /* + * try_fmt has put rectangle within limits. + * S_FMT - use binning and skipping for scaling, recalculate + * limits, used for cropping + */ /* Is this more optimal than just a division? */ for (xskip = 8; xskip > 1; xskip--) - if (rect->width * xskip <= icd->width_max) + if (rect->width * xskip <= MT9T031_MAX_WIDTH) break; for (yskip = 8; yskip > 1; yskip--) - if (rect->height * yskip <= icd->height_max) + if (rect->height * yskip <= MT9T031_MAX_HEIGHT) break; - width = rect->width * xskip; - height = rect->height * yskip; - - dev_dbg(&icd->dev, "xskip %u, width %u, yskip %u, height %u\n", - xskip, width, yskip, height); + recalculate_limits(icd, xskip, yskip); + } else { + /* CROP - no change in scaling, or in limits */ + xskip = mt9t031->xskip; + yskip = mt9t031->yskip; } + /* Make sure we don't exceed sensor limits */ + if (rect->left + rect->width > icd->width_max) + rect->left = (icd->width_max - rect->width) / 2 + icd->x_min; + + if (rect->top + rect->height > icd->height_max) + rect->top = (icd->height_max - rect->height) / 2 + icd->y_min; + + width = rect->width * xskip; + height = rect->height * yskip; + left = rect->left * xskip; + top = rect->top * yskip; + xbin = min(xskip, (u16)3); ybin = min(yskip, (u16)3); - /* Make sure we don't exceed frame limits */ - if (rect->left + width > icd->width_max) - rect->left = (icd->width_max - width) / 2; + dev_dbg(&icd->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", + xskip, width, rect->width, yskip, height, rect->height); - if (rect->top + height > icd->height_max) - rect->top = (icd->height_max - height) / 2; - - /* Could just do roundup(rect->left, [xy]bin); but this is cheaper */ + /* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper */ switch (xbin) { case 2: - rect->left = (rect->left + 1) & ~1; + left = (left + 3) & ~3; break; case 3: - rect->left = roundup(rect->left, 3); + left = roundup(left, 6); } switch (ybin) { case 2: - rect->top = (rect->top + 1) & ~1; + top = (top + 3) & ~3; break; case 3: - rect->top = roundup(rect->top, 3); + top = roundup(top, 6); } + /* Disable register update, reconfigure atomically */ + ret = reg_set(icd, MT9T031_OUTPUT_CONTROL, 1); + if (ret < 0) + return ret; + /* Blanking and start values - default... */ ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank); if (ret >= 0) @@ -270,14 +298,14 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE, ((ybin - 1) << 4) | (yskip - 1)); } - dev_dbg(&icd->dev, "new left %u, top %u\n", rect->left, rect->top); + dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top); /* The caller provides a supported format, as guaranteed by * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ if (ret >= 0) - ret = reg_write(icd, MT9T031_COLUMN_START, rect->left); + ret = reg_write(icd, MT9T031_COLUMN_START, left); if (ret >= 0) - ret = reg_write(icd, MT9T031_ROW_START, rect->top); + ret = reg_write(icd, MT9T031_ROW_START, top); if (ret >= 0) ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1); if (ret >= 0) @@ -302,6 +330,9 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, mt9t031->yskip = yskip; } + /* Re-enable register update, commit all changes */ + reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); + return ret < 0 ? ret : 0; } @@ -310,14 +341,14 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, { struct v4l2_pix_format *pix = &f->fmt.pix; - if (pix->height < icd->height_min) - pix->height = icd->height_min; - if (pix->height > icd->height_max) - pix->height = icd->height_max; - if (pix->width < icd->width_min) - pix->width = icd->width_min; - if (pix->width > icd->width_max) - pix->width = icd->width_max; + if (pix->height < MT9T031_MIN_HEIGHT) + pix->height = MT9T031_MIN_HEIGHT; + if (pix->height > MT9T031_MAX_HEIGHT) + pix->height = MT9T031_MAX_HEIGHT; + if (pix->width < MT9T031_MIN_WIDTH) + pix->width = MT9T031_MIN_WIDTH; + if (pix->width > MT9T031_MAX_WIDTH) + pix->width = MT9T031_MAX_WIDTH; pix->width &= ~0x01; /* has to be even */ pix->height &= ~0x01; /* has to be even */ @@ -389,6 +420,14 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { .maximum = 1, .step = 1, .default_value = 0, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, }, { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -513,21 +552,23 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro if (data < 0) return -EIO; } else { - /* Pack it into 1.125..15 variable step, register values 9..67 */ + /* Pack it into 1.125..128 variable step, register values 9..0x7860 */ /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ unsigned long range = qctrl->maximum - qctrl->default_value - 1; + /* calculated gain: map 65..127 to 9..1024 step 0.125 */ unsigned long gain = ((ctrl->value - qctrl->default_value - 1) * - 111 + range / 2) / range + 9; + 1015 + range / 2) / range + 9; - if (gain <= 32) + if (gain <= 32) /* calculated gain 9..32 -> 9..32 */ data = gain; - else if (gain <= 64) + else if (gain <= 64) /* calculated gain 33..64 -> 0x51..0x60 */ data = ((gain - 32) * 16 + 16) / 32 + 80; else - data = ((gain - 64) * 7 + 28) / 56 + 96; + /* calculated gain 65..1024 -> (1..120) << 8 + 0x60 */ + data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60; - dev_dbg(&icd->dev, "Setting gain from %d to %d\n", - reg_read(icd, MT9T031_GLOBAL_GAIN), data); + dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n", + reg_read(icd, MT9T031_GLOBAL_GAIN), data); data = reg_write(icd, MT9T031_GLOBAL_GAIN, data); if (data < 0) return -EIO; -- cgit v1.2.3 From 9f8456392268399f45cc6a1bc14889c7109975d1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:13:24 +0100 Subject: soc-camera: camera host driver for i.MX3x SoCs From: Guennadi Liakhovetski Tested with 8 bit Bayer and 8 bit monochrome video. Signed-off-by: Guennadi Liakhovetski --- arch/arm/plat-mxc/include/mach/mx3_camera.h | 52 ++ drivers/media/video/Kconfig | 7 + drivers/media/video/Makefile | 5 +- drivers/media/video/mx3_camera.c | 1183 +++++++++++++++++++++++++++ 4 files changed, 1245 insertions(+), 2 deletions(-) create mode 100644 arch/arm/plat-mxc/include/mach/mx3_camera.h create mode 100644 drivers/media/video/mx3_camera.c --- linux/drivers/media/video/Kconfig | 7 + linux/drivers/media/video/Makefile | 5 +- linux/drivers/media/video/mx3_camera.c | 1183 ++++++++++++++++++++++++++++++++ 3 files changed, 1193 insertions(+), 2 deletions(-) create mode 100644 linux/drivers/media/video/mx3_camera.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 19cf3b8f6..3e4ce4aad 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -779,6 +779,13 @@ config SOC_CAMERA_OV772X help This is a ov772x camera driver +config VIDEO_MX3 + tristate "i.MX3x Camera Sensor Interface driver" + depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA + select VIDEOBUF_DMA_CONTIG + ---help--- + This is a v4l2 driver for the i.MX3x Camera Sensor Interface + config VIDEO_PXA27x tristate "PXA27x Quick Capture Interface driver" depends on VIDEO_DEV && PXA27x && SOC_CAMERA diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 72f6d03d2..6e2c69569 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -134,10 +134,11 @@ obj-$(CONFIG_VIDEO_CX18) += cx18/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ -obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o +obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o +obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o -obj-$(CONFIG_SOC_CAMERA) += soc_camera.o +obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c new file mode 100644 index 000000000..a925d093b --- /dev/null +++ b/linux/drivers/media/video/mx3_camera.c @@ -0,0 +1,1183 @@ +/* + * V4L2 Driver for i.MX3x camera host + * + * Copyright (C) 2008 + * Guennadi Liakhovetski, DENX Software Engineering, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define MX3_CAM_DRV_NAME "mx3-camera" + +/* CMOS Sensor Interface Registers */ +#define CSI_REG_START 0x60 + +#define CSI_SENS_CONF (0x60 - CSI_REG_START) +#define CSI_SENS_FRM_SIZE (0x64 - CSI_REG_START) +#define CSI_ACT_FRM_SIZE (0x68 - CSI_REG_START) +#define CSI_OUT_FRM_CTRL (0x6C - CSI_REG_START) +#define CSI_TST_CTRL (0x70 - CSI_REG_START) +#define CSI_CCIR_CODE_1 (0x74 - CSI_REG_START) +#define CSI_CCIR_CODE_2 (0x78 - CSI_REG_START) +#define CSI_CCIR_CODE_3 (0x7C - CSI_REG_START) +#define CSI_FLASH_STROBE_1 (0x80 - CSI_REG_START) +#define CSI_FLASH_STROBE_2 (0x84 - CSI_REG_START) + +#define CSI_SENS_CONF_VSYNC_POL_SHIFT 0 +#define CSI_SENS_CONF_HSYNC_POL_SHIFT 1 +#define CSI_SENS_CONF_DATA_POL_SHIFT 2 +#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT 3 +#define CSI_SENS_CONF_SENS_PRTCL_SHIFT 4 +#define CSI_SENS_CONF_SENS_CLKSRC_SHIFT 7 +#define CSI_SENS_CONF_DATA_FMT_SHIFT 8 +#define CSI_SENS_CONF_DATA_WIDTH_SHIFT 10 +#define CSI_SENS_CONF_EXT_VSYNC_SHIFT 15 +#define CSI_SENS_CONF_DIVRATIO_SHIFT 16 + +#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444 (0UL << CSI_SENS_CONF_DATA_FMT_SHIFT) +#define CSI_SENS_CONF_DATA_FMT_YUV422 (2UL << CSI_SENS_CONF_DATA_FMT_SHIFT) +#define CSI_SENS_CONF_DATA_FMT_BAYER (3UL << CSI_SENS_CONF_DATA_FMT_SHIFT) + +#define MAX_VIDEO_MEM 16 + +struct mx3_camera_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + const struct soc_camera_data_format *fmt; + + /* One descriptot per scatterlist (per frame) */ + struct dma_async_tx_descriptor *txd; + + /* We have to "build" a scatterlist ourselves - one element per frame */ + struct scatterlist sg; +}; + +/** + * struct mx3_camera_dev - i.MX3x camera (CSI) object + * @dev: camera device, to which the coherent buffer is attached + * @icd: currently attached camera sensor + * @clk: pointer to clock + * @base: remapped register base address + * @pdata: platform data + * @platform_flags: platform flags + * @mclk: master clock frequency in Hz + * @capture: list of capture videobuffers + * @lock: protects video buffer lists + * @active: active video buffer + * @idmac_channel: array of pointers to IPU DMAC DMA channels + * @soc_host: embedded soc_host object + */ +struct mx3_camera_dev { + struct device *dev; + /* + * i.MX3x is only supposed to handle one camera on its Camera Sensor + * Interface. If anyone ever builds hardware to enable more than one + * camera _simultaneously_, they will have to modify this driver too + */ + struct soc_camera_device *icd; + struct clk *clk; + + void __iomem *base; + + struct mx3_camera_pdata *pdata; + + unsigned long platform_flags; + unsigned long mclk; + + struct list_head capture; + spinlock_t lock; /* Protects video buffer lists */ + struct mx3_camera_buffer *active; + + /* IDMAC / dmaengine interface */ + struct idmac_channel *idmac_channel[1]; /* We need one channel */ + + struct soc_camera_host soc_host; +}; + +struct dma_chan_request { + struct mx3_camera_dev *mx3_cam; + enum ipu_channel id; +}; + +static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt); + +static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) +{ + return __raw_readl(mx3->base + reg); +} + +static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg) +{ + __raw_writel(value, mx3->base + reg); +} + +/* Called from the IPU IDMAC ISR */ +static void mx3_cam_dma_done(void *arg) +{ + struct idmac_tx_desc *desc = to_tx_desc(arg); + struct dma_chan *chan = desc->txd.chan; + struct idmac_channel *ichannel = to_idmac_chan(chan); + struct mx3_camera_dev *mx3_cam = ichannel->client; + struct videobuf_buffer *vb; + + dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n", + desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0); + + spin_lock(&mx3_cam->lock); + if (mx3_cam->active) { + vb = &mx3_cam->active->vb; + + list_del_init(&vb->queue); + vb->state = VIDEOBUF_DONE; + do_gettimeofday(&vb->ts); + vb->field_count++; + wake_up(&vb->done); + } + + if (list_empty(&mx3_cam->capture)) { + mx3_cam->active = NULL; + spin_unlock(&mx3_cam->lock); + + /* + * stop capture - without further buffers IPU_CHA_BUF0_RDY will + * not get updated + */ + return; + } + + mx3_cam->active = list_entry(mx3_cam->capture.next, + struct mx3_camera_buffer, vb.queue); + mx3_cam->active->vb.state = VIDEOBUF_ACTIVE; + spin_unlock(&mx3_cam->lock); +} + +static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf) +{ + struct soc_camera_device *icd = vq->priv_data; + struct videobuf_buffer *vb = &buf->vb; + struct dma_async_tx_descriptor *txd = buf->txd; + struct idmac_channel *ichan; + + BUG_ON(in_interrupt()); + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + vb, vb->baddr, vb->bsize); + + /* + * This waits until this buffer is out of danger, i.e., until it is no + * longer in STATE_QUEUED or STATE_ACTIVE + */ + videobuf_waiton(vb, 0, 0); + if (txd) { + ichan = to_idmac_chan(txd->chan); + async_tx_ack(txd); + } + videobuf_dma_contig_free(vq, vb); + buf->txd = NULL; + + vb->state = VIDEOBUF_NEEDS_INIT; +} + +/* + * Videobuf operations + */ + +/* + * Calculate the __buffer__ (not data) size and number of buffers. + * Called with .vb_lock held + */ +static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + /* + * bits-per-pixel (depth) as specified in camera's pixel format does + * not necessarily match what the camera interface writes to RAM, but + * it should be good enough for now. + */ + unsigned int bpp = DIV_ROUND_UP(icd->current_fmt->depth, 8); + + if (!mx3_cam->idmac_channel[0]) + return -EINVAL; + + *size = icd->width * icd->height * bpp; + + if (!*count) + *count = 32; + + if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) + *count = MAX_VIDEO_MEM * 1024 * 1024 / *size; + + return 0; +} + +/* Called with .vb_lock held */ +static int mx3_videobuf_prepare(struct videobuf_queue *vq, + struct videobuf_buffer *vb, enum v4l2_field field) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = + container_of(vb, struct mx3_camera_buffer, vb); + /* current_fmt _must_ always be set */ + size_t new_size = icd->width * icd->height * + ((icd->current_fmt->depth + 7) >> 3); + int ret; + + /* + * I think, in buf_prepare you only have to protect global data, + * the actual buffer is yours + */ + + if (buf->fmt != icd->current_fmt || + vb->width != icd->width || + vb->height != icd->height || + vb->field != field) { + buf->fmt = icd->current_fmt; + vb->width = icd->width; + vb->height = icd->height; + vb->field = field; + if (vb->state != VIDEOBUF_NEEDS_INIT) + free_buffer(vq, buf); + } + + if (vb->baddr && vb->bsize < new_size) { + /* User provided buffer, but it is too small */ + ret = -ENOMEM; + goto out; + } + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; + struct scatterlist *sg = &buf->sg; + + /* + * The total size of video-buffers that will be allocated / mapped. + * *size that we calculated in videobuf_setup gets assigned to + * vb->bsize, and now we use the same calculation to get vb->size. + */ + vb->size = new_size; + + /* This actually (allocates and) maps buffers */ + ret = videobuf_iolock(vq, vb, NULL); + if (ret) + goto fail; + + /* + * We will have to configure the IDMAC channel. It has two slots + * for DMA buffers, we shall enter the first two buffers there, + * and then submit new buffers in DMA-ready interrupts + */ + sg_init_table(sg, 1); + sg_dma_address(sg) = videobuf_to_dma_contig(vb); + sg_dma_len(sg) = vb->size; + + buf->txd = ichan->dma_chan.device->device_prep_slave_sg( + &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT); + if (!buf->txd) { + ret = -EIO; + goto fail; + } + + buf->txd->callback_param = buf->txd; + buf->txd->callback = mx3_cam_dma_done; + + vb->state = VIDEOBUF_PREPARED; + } + + return 0; + +fail: + free_buffer(vq, buf); +out: + return ret; +} + +static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) +{ + /* Add more formats as need arises and test possibilities appear... */ + switch (fourcc) { + case V4L2_PIX_FMT_RGB565: + return IPU_PIX_FMT_RGB565; + case V4L2_PIX_FMT_RGB24: + return IPU_PIX_FMT_RGB24; + case V4L2_PIX_FMT_RGB332: + return IPU_PIX_FMT_RGB332; + case V4L2_PIX_FMT_YUV422P: + return IPU_PIX_FMT_YVU422P; + default: + return IPU_PIX_FMT_GENERIC; + } +} + +/* Called with .vb_lock held */ +static void mx3_videobuf_queue(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = + container_of(vb, struct mx3_camera_buffer, vb); + struct dma_async_tx_descriptor *txd = buf->txd; + struct idmac_channel *ichan = to_idmac_chan(txd->chan); + struct idmac_video_param *video = &ichan->params.video; + const struct soc_camera_data_format *data_fmt = icd->current_fmt; + dma_cookie_t cookie; + unsigned long flags; + + /* This is the configuration of one sg-element */ + video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); + video->out_width = icd->width; + video->out_height = icd->height; + video->out_stride = icd->width; + +#ifdef DEBUG + /* helps to see what DMA actually has written */ + memset((void *)vb->baddr, 0xaa, vb->bsize); +#endif + + spin_lock_irqsave(&mx3_cam->lock, flags); + + list_add_tail(&vb->queue, &mx3_cam->capture); + + if (!mx3_cam->active) { + mx3_cam->active = buf; + vb->state = VIDEOBUF_ACTIVE; + } else { + vb->state = VIDEOBUF_QUEUED; + } + + spin_unlock_irqrestore(&mx3_cam->lock, flags); + + cookie = txd->tx_submit(txd); + dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg)); + if (cookie >= 0) + return; + + /* Submit error */ + vb->state = VIDEOBUF_PREPARED; + + spin_lock_irqsave(&mx3_cam->lock, flags); + + list_del_init(&vb->queue); + + if (mx3_cam->active == buf) + mx3_cam->active = NULL; + + spin_unlock_irqrestore(&mx3_cam->lock, flags); +} + +/* Called with .vb_lock held */ +static void mx3_videobuf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = + container_of(vb, struct mx3_camera_buffer, vb); + unsigned long flags; + + dev_dbg(&icd->dev, "Release%s DMA 0x%08x (state %d), queue %sempty\n", + mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg), + vb->state, list_empty(&vb->queue) ? "" : "not "); + spin_lock_irqsave(&mx3_cam->lock, flags); + if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && + !list_empty(&vb->queue)) { + vb->state = VIDEOBUF_ERROR; + + list_del_init(&vb->queue); + if (mx3_cam->active == buf) + mx3_cam->active = NULL; + } + spin_unlock_irqrestore(&mx3_cam->lock, flags); + free_buffer(vq, buf); +} + +static struct videobuf_queue_ops mx3_videobuf_ops = { + .buf_setup = mx3_videobuf_setup, + .buf_prepare = mx3_videobuf_prepare, + .buf_queue = mx3_videobuf_queue, + .buf_release = mx3_videobuf_release, +}; + +static void mx3_camera_init_videobuf(struct videobuf_queue *q, + struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + + videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev, + &mx3_cam->lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_NONE, + sizeof(struct mx3_camera_buffer), icd); +} + +/* First part of ipu_csi_init_interface() */ +static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, + struct soc_camera_device *icd) +{ + u32 conf; + long rate; + + /* Set default size: ipu_csi_set_window_size() */ + csi_reg_write(mx3_cam, (640 - 1) | ((480 - 1) << 16), CSI_ACT_FRM_SIZE); + /* ...and position to 0:0: ipu_csi_set_window_pos() */ + conf = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; + csi_reg_write(mx3_cam, conf, CSI_OUT_FRM_CTRL); + + /* We use only gated clock synchronisation mode so far */ + conf = 0 << CSI_SENS_CONF_SENS_PRTCL_SHIFT; + + /* Set generic data, platform-biggest bus-width */ + conf |= CSI_SENS_CONF_DATA_FMT_BAYER; + + if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) + conf |= 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) + conf |= 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) + conf |= 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else/* if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)*/ + conf |= 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + + if (mx3_cam->platform_flags & MX3_CAMERA_CLK_SRC) + conf |= 1 << CSI_SENS_CONF_SENS_CLKSRC_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_EXT_VSYNC) + conf |= 1 << CSI_SENS_CONF_EXT_VSYNC_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_DP) + conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_PCP) + conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_HSP) + conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_VSP) + conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; + + /* ipu_csi_init_interface() */ + csi_reg_write(mx3_cam, conf, CSI_SENS_CONF); + + clk_enable(mx3_cam->clk); + rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); + dev_dbg(&icd->dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate); + if (rate) + clk_set_rate(mx3_cam->clk, rate); +} + +/* Called with .video_lock held */ +static int mx3_camera_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + int ret; + + if (mx3_cam->icd) { + ret = -EBUSY; + goto ebusy; + } + + mx3_camera_activate(mx3_cam, icd); + ret = icd->ops->init(icd); + if (ret < 0) { + clk_disable(mx3_cam->clk); + goto einit; + } + + mx3_cam->icd = icd; + +einit: +ebusy: + if (!ret) + dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", + icd->devnum); + + return ret; +} + +/* Called with .video_lock held */ +static void mx3_camera_remove_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; + + BUG_ON(icd != mx3_cam->icd); + + if (*ichan) { + dma_release_channel(&(*ichan)->dma_chan); + *ichan = NULL; + } + + icd->ops->release(icd); + + clk_disable(mx3_cam->clk); + + mx3_cam->icd = NULL; + + dev_info(&icd->dev, "MX3 Camera driver detached from camera %d\n", + icd->devnum); +} + +static bool channel_change_requested(struct soc_camera_device *icd, + const struct soc_camera_format_xlate *xlate, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; + + /* So far only one configuration is supported */ + return pixfmt || (ichan && rect->width * rect->height > + icd->width * icd->height); +} + +static int test_platform_param(struct mx3_camera_dev *mx3_cam, + unsigned char buswidth, unsigned long *flags) +{ + /* + * Platform specified synchronization and pixel clock polarities are + * only a recommendation and are only used during probing. MX3x + * camera interface only works in master mode, i.e., uses HSYNC and + * VSYNC signals from the sensor + */ + *flags = SOCAM_MASTER | + SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_HSYNC_ACTIVE_LOW | + SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_PCLK_SAMPLE_RISING | + SOCAM_PCLK_SAMPLE_FALLING | + SOCAM_DATA_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_LOW; + + /* If requested data width is supported by the platform, use it or any + * possible lower value - i.MX31 is smart enough to schift bits */ + switch (buswidth) { + case 15: + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 | + SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; + break; + case 10: + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 | + SOCAM_DATAWIDTH_4; + break; + case 8: + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; + break; + case 4: + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_4; + break; + default: + dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth); + return -EINVAL; + } + + return 0; +} + +static int mx3_camera_try_bus_param(struct soc_camera_device *icd, + const unsigned int depth) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + unsigned long bus_flags, camera_flags; + int ret = test_platform_param(mx3_cam, depth, &bus_flags); + + dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret); + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + ret = soc_camera_bus_param_compatible(camera_flags, bus_flags); + if (ret < 0) + dev_warn(&icd->dev, "Flags incompatible: camera %lx, host %lx\n", + camera_flags, bus_flags); + + return ret; +} + +static bool chan_filter(struct dma_chan *chan, void *arg) +{ + struct dma_chan_request *rq = arg; + struct mx3_camera_pdata *pdata; + + if (!rq) + return false; + + pdata = rq->mx3_cam->dev->platform_data; + + return rq->id == chan->chan_id && + pdata->dma_dev == chan->device->dev; +} + +static const struct soc_camera_data_format mx3_camera_formats[] = { + { + .name = "Bayer (sRGB) 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "Monochrome 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_GREY, + .colorspace = V4L2_COLORSPACE_JPEG, + }, +}; + +static bool buswidth_supported(struct soc_camera_host *ici, int depth) +{ + struct mx3_camera_dev *mx3_cam = ici->priv; + + switch (depth) { + case 4: + return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4); + case 8: + return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8); + case 10: + return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10); + case 15: + return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15); + } + return false; +} + +static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, + struct soc_camera_format_xlate *xlate) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int formats = 0, buswidth, ret; + + buswidth = icd->formats[idx].depth; + + if (!buswidth_supported(ici, buswidth)) + return 0; + + ret = mx3_camera_try_bus_param(icd, buswidth); + if (ret < 0) + return 0; + + switch (icd->formats[idx].fourcc) { + case V4L2_PIX_FMT_SGRBG10: + formats++; + if (xlate) { + xlate->host_fmt = &mx3_camera_formats[0]; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = buswidth; + xlate++; + dev_dbg(&ici->dev, "Providing format %s using %s\n", + mx3_camera_formats[0].name, + icd->formats[idx].name); + } + goto passthrough; + case V4L2_PIX_FMT_Y16: + formats++; + if (xlate) { + xlate->host_fmt = &mx3_camera_formats[1]; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = buswidth; + xlate++; + dev_dbg(&ici->dev, "Providing format %s using %s\n", + mx3_camera_formats[0].name, + icd->formats[idx].name); + } + default: +passthrough: + /* Generic pass-through */ + formats++; + if (xlate) { + xlate->host_fmt = icd->formats + idx; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = buswidth; + xlate++; + dev_dbg(&ici->dev, + "Providing format %s in pass-through mode\n", + icd->formats[idx].name); + } + } + + return formats; +} + +static int mx3_camera_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + const struct soc_camera_format_xlate *xlate; + u32 ctrl, width_field, height_field; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (pixfmt && !xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + /* + * We now know pixel formats and can decide upon DMA-channel(s) + * So far only direct camera-to-memory is supported + */ + if (channel_change_requested(icd, xlate, pixfmt, rect)) { + dma_cap_mask_t mask; + struct dma_chan *chan; + struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; + /* We have to use IDMAC_IC_7 for Bayer / generic data */ + struct dma_chan_request rq = {.mx3_cam = mx3_cam, + .id = IDMAC_IC_7}; + + if (*ichan) { + struct videobuf_buffer *vb, *_vb; + dma_release_channel(&(*ichan)->dma_chan); + *ichan = NULL; + mx3_cam->active = NULL; + list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) { + list_del_init(&vb->queue); + vb->state = VIDEOBUF_ERROR; + wake_up(&vb->done); + } + } + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + chan = dma_request_channel(mask, chan_filter, &rq); + if (!chan) + return -EBUSY; + + *ichan = to_idmac_chan(chan); + (*ichan)->client = mx3_cam; + } + + /* + * Might have to perform a complete interface initialisation like in + * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider + * mxc_v4l2_s_fmt() + */ + + /* Setup frame size - this cannot be changed on-the-fly... */ + width_field = rect->width - 1; + height_field = rect->height - 1; + csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_SENS_FRM_SIZE); + + csi_reg_write(mx3_cam, width_field << 16, CSI_FLASH_STROBE_1); + csi_reg_write(mx3_cam, (height_field << 16) | 0x22, CSI_FLASH_STROBE_2); + + csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_ACT_FRM_SIZE); + + /* ...and position */ + ctrl = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; + /* Sensor does the cropping */ + csi_reg_write(mx3_cam, ctrl | 0 | (0 << 8), CSI_OUT_FRM_CTRL); + + /* + * No need to free resources here if we fail, we'll see if we need to + * do this next time we are called + */ + + ret = icd->ops->set_fmt(icd, pixfmt ? xlate->cam_fmt->fourcc : 0, rect); + if (pixfmt && !ret) { + icd->buswidth = xlate->buswidth; + icd->current_fmt = xlate->host_fmt; + } + + return ret; +} + +static int mx3_camera_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + __u32 pixfmt = pix->pixelformat; + enum v4l2_field field; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (pixfmt && !xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + /* limit to MX3 hardware capabilities */ + if (pix->height > 4096) + pix->height = 4096; + if (pix->width > 4096) + pix->width = 4096; + + pix->bytesperline = pix->width * + DIV_ROUND_UP(xlate->host_fmt->depth, 8); + pix->sizeimage = pix->height * pix->bytesperline; + + /* camera has to see its format, but the user the original one */ + pix->pixelformat = xlate->cam_fmt->fourcc; + /* limit to sensor capabilities */ + ret = icd->ops->try_fmt(icd, f); + pix->pixelformat = xlate->host_fmt->fourcc; + + field = pix->field; + + if (field == V4L2_FIELD_ANY) { + pix->field = V4L2_FIELD_NONE; + } else if (field != V4L2_FIELD_NONE) { + dev_err(&icd->dev, "Field type %d unsupported.\n", field); + return -EINVAL; + } + + return ret; +} + +static int mx3_camera_reqbufs(struct soc_camera_file *icf, + struct v4l2_requestbuffers *p) +{ + return 0; +} + +static unsigned int mx3_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + + return videobuf_poll_stream(file, &icf->vb_vidq, pt); +} + +static int mx3_camera_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the firendly caller:-> */ + strlcpy(cap->card, "i.MX3x Camera", sizeof(cap->card)); + cap->version = KERNEL_VERSION(0, 2, 2); + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + + return 0; +} + +static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + unsigned long bus_flags, camera_flags, common_flags; + u32 dw, sens_conf; + int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags); + const struct soc_camera_format_xlate *xlate; + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", + icd->buswidth, ret); + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); + if (!common_flags) { + dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n", + camera_flags, bus_flags); + return -EINVAL; + } + + /* Make choices, based on platform preferences */ + if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_HSP) + common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_VSP) + common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) && + (common_flags & SOCAM_DATA_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_DP) + common_flags &= ~SOCAM_DATA_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_DATA_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && + (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { + if (mx3_cam->platform_flags & MX3_CAMERA_PCP) + common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; + else + common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; + } + + /* Make the camera work in widest common mode, we'll take care of + * the rest */ + if (common_flags & SOCAM_DATAWIDTH_15) + common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | + SOCAM_DATAWIDTH_15; + else if (common_flags & SOCAM_DATAWIDTH_10) + common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | + SOCAM_DATAWIDTH_10; + else if (common_flags & SOCAM_DATAWIDTH_8) + common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | + SOCAM_DATAWIDTH_8; + else + common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | + SOCAM_DATAWIDTH_4; + + ret = icd->ops->set_bus_param(icd, common_flags); + if (ret < 0) + return ret; + + /* + * So far only gated clock mode is supported. Add a line + * (3 << CSI_SENS_CONF_SENS_PRTCL_SHIFT) | + * below and select the required mode when supporting other + * synchronisation protocols. + */ + sens_conf = csi_reg_read(mx3_cam, CSI_SENS_CONF) & + ~((1 << CSI_SENS_CONF_VSYNC_POL_SHIFT) | + (1 << CSI_SENS_CONF_HSYNC_POL_SHIFT) | + (1 << CSI_SENS_CONF_DATA_POL_SHIFT) | + (1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT) | + (3 << CSI_SENS_CONF_DATA_FMT_SHIFT) | + (3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT)); + + /* TODO: Support RGB and YUV formats */ + + /* This has been set in mx3_camera_activate(), but we clear it above */ + sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER; + + if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) + sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; + if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; + if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; + if (common_flags & SOCAM_DATA_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; + + /* Just do what we're asked to do */ + switch (xlate->host_fmt->depth) { + case 4: + dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + case 8: + dw = 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + case 10: + dw = 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + default: + /* + * Actually it can only be 15 now, default is just to silence + * compiler warnings + */ + case 15: + dw = 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + } + + csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); + + dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw); + + return 0; +} + +static struct soc_camera_host_ops mx3_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = mx3_camera_add_device, + .remove = mx3_camera_remove_device, +#ifdef CONFIG_PM + .suspend = mx3_camera_suspend, + .resume = mx3_camera_resume, +#endif + .set_fmt = mx3_camera_set_fmt, + .try_fmt = mx3_camera_try_fmt, + .get_formats = mx3_camera_get_formats, + .init_videobuf = mx3_camera_init_videobuf, + .reqbufs = mx3_camera_reqbufs, + .poll = mx3_camera_poll, + .querycap = mx3_camera_querycap, + .set_bus_param = mx3_camera_set_bus_param, +}; + +static int mx3_camera_probe(struct platform_device *pdev) +{ + struct mx3_camera_dev *mx3_cam; + struct resource *res; + void __iomem *base; + int err = 0; + struct soc_camera_host *soc_host; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -ENODEV; + goto egetres; + } + + mx3_cam = vmalloc(sizeof(*mx3_cam)); + if (!mx3_cam) { + dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); + err = -ENOMEM; + goto ealloc; + } + memset(mx3_cam, 0, sizeof(*mx3_cam)); + + mx3_cam->clk = clk_get(&pdev->dev, "csi_clk"); + if (IS_ERR(mx3_cam->clk)) { + err = PTR_ERR(mx3_cam->clk); + goto eclkget; + } + + dev_set_drvdata(&pdev->dev, mx3_cam); + + mx3_cam->pdata = pdev->dev.platform_data; + mx3_cam->platform_flags = mx3_cam->pdata->flags; + if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 | + MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 | + MX3_CAMERA_DATAWIDTH_15))) { + /* Platform hasn't set available data widths. This is bad. + * Warn and use a default. */ + dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " + "data widths, using default 8 bit\n"); + mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8; + } + + mx3_cam->mclk = mx3_cam->pdata->mclk_10khz * 10000; + if (!mx3_cam->mclk) { + dev_warn(&pdev->dev, + "mclk_10khz == 0! Please, fix your platform data. " + "Using default 20MHz\n"); + mx3_cam->mclk = 20000000; + } + + /* list of video-buffers */ + INIT_LIST_HEAD(&mx3_cam->capture); + spin_lock_init(&mx3_cam->lock); + + base = ioremap(res->start, res->end - res->start + 1); + if (!base) { + err = -ENOMEM; + goto eioremap; + } + + mx3_cam->base = base; + mx3_cam->dev = &pdev->dev; + + soc_host = &mx3_cam->soc_host; + soc_host->drv_name = MX3_CAM_DRV_NAME; + soc_host->ops = &mx3_soc_camera_host_ops; + soc_host->priv = mx3_cam; + soc_host->dev.parent = &pdev->dev; + soc_host->nr = pdev->id; + err = soc_camera_host_register(soc_host); + if (err) + goto ecamhostreg; + + /* IDMAC interface */ + dmaengine_get(); + + return 0; + +ecamhostreg: + iounmap(base); +eioremap: + clk_put(mx3_cam->clk); +eclkget: + vfree(mx3_cam); +ealloc: +egetres: + return err; +} + +static int __devexit mx3_camera_remove(struct platform_device *pdev) +{ + struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev); + + clk_put(mx3_cam->clk); + + soc_camera_host_unregister(&mx3_cam->soc_host); + + iounmap(mx3_cam->base); + + /* + * The channel has either not been allocated, + * or should have been released + */ + if (WARN_ON(mx3_cam->idmac_channel[0])) + dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan); + + vfree(mx3_cam); + + dmaengine_put(); + + dev_info(&pdev->dev, "i.MX3x Camera driver unloaded\n"); + + return 0; +} + +static struct platform_driver mx3_camera_driver = { + .driver = { + .name = MX3_CAM_DRV_NAME, + }, + .probe = mx3_camera_probe, + .remove = __exit_p(mx3_camera_remove), +}; + + +static int __devinit mx3_camera_init(void) +{ + return platform_driver_register(&mx3_camera_driver); +} + +static void __exit mx3_camera_exit(void) +{ + platform_driver_unregister(&mx3_camera_driver); +} + +module_init(mx3_camera_init); +module_exit(mx3_camera_exit); + +MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From a43bb4e65ce2015ec503f7933fbd136271d80c34 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 16:13:24 +0100 Subject: mt9m111: Call icl->reset() on mt9m111_reset(). From: Antonio Ospite Call icl->reset() on mt9m111_reset(). Signed-off-by: Antonio Ospite Acked-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m111.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) --- linux/drivers/media/video/mt9m111.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index b2989c0f2..3ae675a42 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -393,6 +393,8 @@ static int mt9m111_disable(struct soc_camera_device *icd) static int mt9m111_reset(struct soc_camera_device *icd) { + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct soc_camera_link *icl = mt9m111->client->dev.platform_data; int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); @@ -401,6 +403,10 @@ static int mt9m111_reset(struct soc_camera_device *icd) if (!ret) ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE | MT9M111_RESET_RESET_SOC); + + if (icl->reset) + icl->reset(&mt9m111->client->dev); + return ret; } -- cgit v1.2.3 From f1b096388308b69fdc4fe54e5952a7f7beb845bb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Feb 2009 15:26:38 +0000 Subject: remove redundant memset after kzalloc From: Matthias Schwarzott Hi there! While having a look at the allocation of struct dvb_frontend in *_attach functions, I found some cases calling memset after kzalloc. This is redundant, and the attached patch removes these calls. I also changed one case calling kmalloc and memset to kzalloc. Regards Matthias Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/cx24113.c | 2 +- linux/drivers/media/dvb/frontends/cx24116.c | 5 +---- linux/drivers/media/dvb/frontends/cx24123.c | 4 ++-- linux/drivers/media/dvb/frontends/lgdt3304.c | 1 - linux/drivers/media/dvb/frontends/s921_module.c | 1 - 5 files changed, 4 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index f6e7b0380..e4fd533a4 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -559,7 +559,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, kzalloc(sizeof(struct cx24113_state), GFP_KERNEL); int rc; if (state == NULL) { - err("Unable to kmalloc\n"); + err("Unable to kzalloc\n"); goto error; } diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c index 8301a9865..b5ff0b6a8 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.c +++ b/linux/drivers/media/dvb/frontends/cx24116.c @@ -1112,13 +1112,10 @@ struct dvb_frontend *cx24116_attach(const struct cx24116_config *config, dprintk("%s\n", __func__); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL); + state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL); if (state == NULL) goto error1; - /* setup the state */ - memset(state, 0, sizeof(struct cx24116_state)); - state->config = config; state->i2c = i2c; diff --git a/linux/drivers/media/dvb/frontends/cx24123.c b/linux/drivers/media/dvb/frontends/cx24123.c index c9cfc8393..f431f0c56 100644 --- a/linux/drivers/media/dvb/frontends/cx24123.c +++ b/linux/drivers/media/dvb/frontends/cx24123.c @@ -1084,13 +1084,13 @@ static struct dvb_frontend_ops cx24123_ops; struct dvb_frontend *cx24123_attach(const struct cx24123_config *config, struct i2c_adapter *i2c) { + /* allocate memory for the internal state */ struct cx24123_state *state = kzalloc(sizeof(struct cx24123_state), GFP_KERNEL); dprintk("\n"); - /* allocate memory for the internal state */ if (state == NULL) { - err("Unable to kmalloc\n"); + err("Unable to kzalloc\n"); goto error; } diff --git a/linux/drivers/media/dvb/frontends/lgdt3304.c b/linux/drivers/media/dvb/frontends/lgdt3304.c index d56a799d3..3a4a18970 100644 --- a/linux/drivers/media/dvb/frontends/lgdt3304.c +++ b/linux/drivers/media/dvb/frontends/lgdt3304.c @@ -383,7 +383,6 @@ struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, struct lgdt3304_state *state; state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL); - memset(state, 0x0, sizeof(struct lgdt3304_state)); state->addr = config->i2c_address; state->i2c = i2c; diff --git a/linux/drivers/media/dvb/frontends/s921_module.c b/linux/drivers/media/dvb/frontends/s921_module.c index 8ae0676a5..4a673c184 100644 --- a/linux/drivers/media/dvb/frontends/s921_module.c +++ b/linux/drivers/media/dvb/frontends/s921_module.c @@ -233,7 +233,6 @@ struct dvb_frontend* s921_attach(const struct s921_config *config, struct s921_state *state; state = kzalloc(sizeof(struct s921_state), GFP_KERNEL); - memset(state, 0x0, sizeof(struct s921_state)); state->addr = config->i2c_address; state->i2c = i2c; -- cgit v1.2.3 From 0d71a5b1e67685e20608b2b2c1cab61039ee2168 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 25 Feb 2009 09:06:13 -0300 Subject: em28xx: VideoMate For You USB TV box requires tvaudio From: Mauro Carvalho Chehab As reported by Vitaly Wool : > about half a year ago I posted the patch that basically enabled Compro > VideoMate For You USB TV box support. > The main problem is I couldn't get the sound working. > So I kind of decomposed the box and found out the audio decoder chip > used there was Philips TDA9874A. As far as I can see, it's not supported > within the em28xx suite although it is for other TV tuner drivers. A tvaudio modprobing confirms that tda9874a chip is accessible via i2c: tvaudio: TV audio decoder + audio/video mux driver tvaudio: known chips: tda9840, tda9873h, tda9874h/a, tda9850, tda9855, tea6300, tea6320, tea6420, tda8425, pic16c54 (PV951), ta8874z tvaudio' 1-0058: chip found @ 0xb0 tvaudio' 1-0058: tvaudio': chip_read2: reg254=0x11 tvaudio' 1-0058: tvaudio': chip_read2: reg255=0x2 tvaudio' 1-0058: tda9874a_checkit(): DIC=0x11, SIC=0x2. tvaudio' 1-0058: found tda9874a. tvaudio' 1-0058: tda9874h/a found @ 0xb0 (em28xx #0) tvaudio' 1-0058: tda9874h/a: chip_write: reg0=0x0 tvaudio' 1-0058: tda9874h/a: chip_write: reg1=0xc0 tvaudio' 1-0058: tda9874h/a: chip_write: reg2=0x2 tvaudio' 1-0058: tda9874h/a: chip_write: reg11=0x80 tvaudio' 1-0058: tda9874h/a: chip_write: reg12=0x0 tvaudio' 1-0058: tda9874h/a: chip_write: reg13=0x0 tvaudio' 1-0058: tda9874h/a: chip_write: reg14=0x1 tvaudio' 1-0058: tda9874h/a: chip_write: reg15=0x0 tvaudio' 1-0058: tda9874h/a: chip_write: reg16=0x14 tvaudio' 1-0058: tda9874h/a: chip_write: reg17=0x50 tvaudio' 1-0058: tda9874h/a: chip_write: reg18=0xf9 tvaudio' 1-0058: tda9874h/a: chip_write: reg19=0x80 tvaudio' 1-0058: tda9874h/a: chip_write: reg20=0x80 tvaudio' 1-0058: tda9874h/a: chip_write: reg24=0x80 tvaudio' 1-0058: tda9874h/a: chip_write: reg255=0x0 tvaudio' 1-0058: tda9874a_setup(): A2, B/G [0x00]. tvaudio' 1-0058: tda9874h/a: thread started] This patch automatically loads tvaudio when needed (currently, only with this board). Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 3 +++ linux/drivers/media/video/em28xx/em28xx.h | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 5af4c417a..bab6340da 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1309,6 +1309,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, + .adecoder = EM28XX_TVAUDIO, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1986,6 +1987,8 @@ void em28xx_card_setup(struct em28xx *dev) request_module("tvp5150"); if (dev->board.tuner_type != TUNER_ABSENT) request_module("tuner"); + if (dev->board.adecoder == EM28XX_TVAUDIO) + request_module("tvaudio"); #endif em28xx_config_tuner(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 4aebda6c7..e21f29b99 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -358,6 +358,11 @@ enum em28xx_decoder { EM28XX_SAA711X, }; +enum em28xx_adecoder { + EM28XX_NOADECODER = 0, + EM28XX_TVAUDIO, +}; + struct em28xx_board { char *name; int vchannels; @@ -383,6 +388,7 @@ struct em28xx_board { unsigned char xclk, i2c_speed; enum em28xx_decoder decoder; + enum em28xx_adecoder adecoder; struct em28xx_input input[MAX_EM28XX_INPUT]; struct em28xx_input radio; -- cgit v1.2.3 From 4962852576d7148c1fc33d91b533f991902b1b85 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 25 Feb 2009 16:52:31 -0300 Subject: em28xx-cards: remove incorrect entry From: Douglas Schilling Landgraf Removed EM2821_BOARD_PROLINK_PLAYTV_USB2 entry. This entry has a incorrect tuner set. Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 20 -------------------- linux/drivers/media/video/em28xx/em28xx.h | 1 - 2 files changed, 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index bab6340da..ac0e89039 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -382,26 +382,6 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, } }, }, - [EM2821_BOARD_PROLINK_PLAYTV_USB2] = { - .name = "SIIG AVTuner-PVR/Prolink PlayTV USB 2.0", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, /* unknown? */ - .tda9887_conf = TDA9887_PRESENT, /* unknown? */ - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, [EM2821_BOARD_SUPERCOMP_USB_2] = { .name = "Supercomp USB 2.0 TV", .valid = EM28XX_BOARD_NOT_VALIDATED, diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index e21f29b99..235b63499 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -71,7 +71,6 @@ #define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 #define EM2821_BOARD_USBGEAR_VD204 31 #define EM2821_BOARD_SUPERCOMP_USB_2 32 -#define EM2821_BOARD_PROLINK_PLAYTV_USB2 33 #define EM2860_BOARD_TERRATEC_HYBRID_XS 34 #define EM2860_BOARD_TYPHOON_DVD_MAKER 35 #define EM2860_BOARD_NETGMBH_CAM 36 -- cgit v1.2.3 From 429533eb1b620a0ec8153c6b326e6cdd3b8ae924 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 25 Feb 2009 16:54:31 -0300 Subject: em28xx-cards: Add SIIG AVTuner-PVR board From: Douglas Schilling Landgraf Added SIIG AVTuner-PVR to the right entry. Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index ac0e89039..c52ebc3c2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -992,7 +992,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { - .name = "Pixelview Prolink PlayTV USB 2.0", + .name = "SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0", .has_snapshot_button = 1, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, -- cgit v1.2.3 From aadfffeee708815b191d2cdccaf359c284267143 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 25 Feb 2009 16:55:48 -0300 Subject: em28xx: Add Kaiser Baas Video to DVD maker support From: Douglas Schilling Landgraf Added usb vendor/product id for Kaiser Baas Video to DVD maker. Thanks to Trevor Campbell for providing all data and tests needed to add this card to em28xx driver. Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index c52ebc3c2..74f35b6d6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -937,7 +937,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/DVC 100/DVC 101/DVC 107", + .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker", .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { @@ -1414,6 +1414,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2800_BOARD_GRABBEEX_USB2800 }, { USB_DEVICE(0xeb1a, 0xe357), .driver_info = EM2870_BOARD_KWORLD_355U }, + { USB_DEVICE(0x1b80, 0xe302), + .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */ { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, { USB_DEVICE(0x0ccd, 0x004c), -- cgit v1.2.3 From 82b686055fe8bd37d7f9fa64c798834b755bd03d Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Thu, 26 Feb 2009 08:40:41 +0200 Subject: dm1105: not demuxing from interrupt context. From: Igor M. Liplianin The driver already has DMA buffer organized like ringbuffer, so it is easy to switch to a work queue. Length of ringbuffer can easily be increased, if someone need it. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/dm1105/dm1105.c | 122 +++++++++++++++++++------------- 1 file changed, 72 insertions(+), 50 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c index b054d056d..ba053678d 100644 --- a/linux/drivers/media/dvb/dm1105/dm1105.c +++ b/linux/drivers/media/dvb/dm1105/dm1105.c @@ -220,10 +220,14 @@ struct dm1105dvb { /* i2c */ struct i2c_adapter i2c_adap; + /* irq */ + struct work_struct work; + /* dma */ dma_addr_t dma_addr; unsigned char *ts_buf; u32 wrp; + u32 nextwrp; u32 buffer_size; unsigned int PacketErrorCount; unsigned int dmarst; @@ -418,6 +422,9 @@ static void dm1105_emit_key(unsigned long parm) u8 data; u16 keycode; + if (ir_debug) + printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom); + data = (ircom >> 8) & 0x7f; input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data); @@ -434,6 +441,50 @@ static void dm1105_emit_key(unsigned long parm) } +/* work handler */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void dm1105_dmx_buffer(void *_dm1105dvb) +#else +static void dm1105_dmx_buffer(struct work_struct *work) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + struct dm1105dvb *dm1105dvb = _dm1105dvb; +#else + struct dm1105dvb *dm1105dvb = + container_of(work, struct dm1105dvb, work); +#endif + unsigned int nbpackets; + u32 oldwrp = dm1105dvb->wrp; + u32 nextwrp = dm1105dvb->nextwrp; + + if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) && + (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) && + (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) { + dm1105dvb->PacketErrorCount++; + /* bad packet found */ + if ((dm1105dvb->PacketErrorCount >= 2) && + (dm1105dvb->dmarst == 0)) { + outb(1, dm_io_mem(DM1105_RST)); + dm1105dvb->wrp = 0; + dm1105dvb->PacketErrorCount = 0; + dm1105dvb->dmarst = 0; + return; + } + } + + if (nextwrp < oldwrp) { + memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, + dm1105dvb->ts_buf, nextwrp); + nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188; + } else + nbpackets = (nextwrp - oldwrp) / 188; + + dm1105dvb->wrp = nextwrp; + dvb_dmx_swfilter_packets(&dm1105dvb->demux, + &dm1105dvb->ts_buf[oldwrp], nbpackets); +} + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) static irqreturn_t dm1105dvb_irq(int irq, void *dev_id, struct pt_regs *regs) #else @@ -441,11 +492,6 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) #endif { struct dm1105dvb *dm1105dvb = dev_id; - unsigned int piece; - unsigned int nbpackets; - u32 command; - u32 nextwrp; - u32 oldwrp; /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */ unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS)); @@ -454,48 +500,17 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) switch (intsts) { case INTSTS_TSIRQ: case (INTSTS_TSIRQ | INTSTS_IR): - nextwrp = inl(dm_io_mem(DM1105_WRP)) - - inl(dm_io_mem(DM1105_STADR)) ; - oldwrp = dm1105dvb->wrp; - spin_lock(&dm1105dvb->lock); - if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) && - (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) && - (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) { - dm1105dvb->PacketErrorCount++; - /* bad packet found */ - if ((dm1105dvb->PacketErrorCount >= 2) && - (dm1105dvb->dmarst == 0)) { - outb(1, dm_io_mem(DM1105_RST)); - dm1105dvb->wrp = 0; - dm1105dvb->PacketErrorCount = 0; - dm1105dvb->dmarst = 0; - spin_unlock(&dm1105dvb->lock); - return IRQ_HANDLED; - } - } - if (nextwrp < oldwrp) { - piece = dm1105dvb->buffer_size - oldwrp; - memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp); - nbpackets = (piece + nextwrp)/188; - } else { - nbpackets = (nextwrp - oldwrp)/188; - } - dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets); - dm1105dvb->wrp = nextwrp; - spin_unlock(&dm1105dvb->lock); + dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) - + inl(dm_io_mem(DM1105_STADR)); + schedule_work(&dm1105dvb->work); break; case INTSTS_IR: - command = inl(dm_io_mem(DM1105_IRCODE)); - if (ir_debug) - printk("dm1105: received byte 0x%04x\n", command); - - dm1105dvb->ir.ir_command = command; + dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); tasklet_schedule(&dm1105dvb->ir.ir_tasklet); break; } - return IRQ_HANDLED; - + return IRQ_HANDLED; } /* register with input layer */ @@ -717,7 +732,7 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); if (!dm1105dvb) - goto out; + return -ENOMEM; dm1105dvb->pdev = pdev; dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; @@ -747,13 +762,9 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, spin_lock_init(&dm1105dvb->lock); pci_set_drvdata(pdev, dm1105dvb); - ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb); - if (ret < 0) - goto err_pci_iounmap; - ret = dm1105dvb_hw_init(dm1105dvb); if (ret < 0) - goto err_free_irq; + goto err_pci_iounmap; /* i2c */ i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb); @@ -820,8 +831,19 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx); dm1105_ir_init(dm1105dvb); -out: - return ret; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer, dm1105dvb); +#else + INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer); +#endif + + ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, + DRIVER_NAME, dm1105dvb); + if (ret < 0) + goto err_free_irq; + + return 0; err_disconnect_frontend: dmx->disconnect_frontend(dmx); @@ -850,7 +872,7 @@ err_pci_disable_device: err_kfree: pci_set_drvdata(pdev, NULL); kfree(dm1105dvb); - goto out; + return ret; } static void __devexit dm1105_remove(struct pci_dev *pdev) -- cgit v1.2.3 From 8f0863991e64abea1e4ff0141175905a2a9c5529 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Thu, 26 Feb 2009 08:49:44 +0200 Subject: dm1105: infrared remote code is remaked. From: Igor M. Liplianin The driver infrared remote code part is altered to switch to a work queue. Also ir_codes table moved to ir-common module for shared access. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/common/ir-keymaps.c | 38 +++++++++++ linux/drivers/media/dvb/dm1105/dm1105.c | 117 ++++++++++---------------------- 2 files changed, 72 insertions(+), 83 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 827e65582..d5fd71968 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2762,3 +2762,41 @@ IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); + +/* DVBWorld remotes + Igor M. Liplianin + */ +IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { + [0x0a] = KEY_Q, /*power*/ + [0x0c] = KEY_M, /*mute*/ + [0x11] = KEY_1, + [0x12] = KEY_2, + [0x13] = KEY_3, + [0x14] = KEY_4, + [0x15] = KEY_5, + [0x16] = KEY_6, + [0x17] = KEY_7, + [0x18] = KEY_8, + [0x19] = KEY_9, + [0x10] = KEY_0, + [0x1c] = KEY_PAGEUP, /*ch+*/ + [0x0f] = KEY_PAGEDOWN, /*ch-*/ + [0x1a] = KEY_O, /*vol+*/ + [0x0e] = KEY_Z, /*vol-*/ + [0x04] = KEY_R, /*rec*/ + [0x09] = KEY_D, /*fav*/ + [0x08] = KEY_BACKSPACE, /*rewind*/ + [0x07] = KEY_A, /*fast*/ + [0x0b] = KEY_P, /*pause*/ + [0x02] = KEY_ESC, /*cancel*/ + [0x03] = KEY_G, /*tab*/ + [0x00] = KEY_UP, /*up*/ + [0x1f] = KEY_ENTER, /*ok*/ + [0x01] = KEY_DOWN, /*down*/ + [0x05] = KEY_C, /*cap*/ + [0x06] = KEY_S, /*stop*/ + [0x40] = KEY_F, /*full*/ + [0x1e] = KEY_W, /*tvmode*/ + [0x1b] = KEY_B, /*recall*/ +}; +EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c index ba053678d..5d8afefca 100644 --- a/linux/drivers/media/dvb/dm1105/dm1105.c +++ b/linux/drivers/media/dvb/dm1105/dm1105.c @@ -156,46 +156,12 @@ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static u16 ir_codes_dm1105_nec[128] = { - [0x0a] = KEY_Q, /*power*/ - [0x0c] = KEY_M, /*mute*/ - [0x11] = KEY_1, - [0x12] = KEY_2, - [0x13] = KEY_3, - [0x14] = KEY_4, - [0x15] = KEY_5, - [0x16] = KEY_6, - [0x17] = KEY_7, - [0x18] = KEY_8, - [0x19] = KEY_9, - [0x10] = KEY_0, - [0x1c] = KEY_PAGEUP, /*ch+*/ - [0x0f] = KEY_PAGEDOWN, /*ch-*/ - [0x1a] = KEY_O, /*vol+*/ - [0x0e] = KEY_Z, /*vol-*/ - [0x04] = KEY_R, /*rec*/ - [0x09] = KEY_D, /*fav*/ - [0x08] = KEY_BACKSPACE, /*rewind*/ - [0x07] = KEY_A, /*fast*/ - [0x0b] = KEY_P, /*pause*/ - [0x02] = KEY_ESC, /*cancel*/ - [0x03] = KEY_G, /*tab*/ - [0x00] = KEY_UP, /*up*/ - [0x1f] = KEY_ENTER, /*ok*/ - [0x01] = KEY_DOWN, /*down*/ - [0x05] = KEY_C, /*cap*/ - [0x06] = KEY_S, /*stop*/ - [0x40] = KEY_F, /*full*/ - [0x1e] = KEY_W, /*tvmode*/ - [0x1b] = KEY_B, /*recall*/ -}; - /* infrared remote control */ struct infrared { - u16 key_map[128]; struct input_dev *input_dev; + struct ir_input_state ir; char input_phys[32]; - struct tasklet_struct ir_tasklet; + struct work_struct work; u32 ir_command; }; @@ -237,8 +203,6 @@ struct dm1105dvb { #define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg])) -static struct dm1105dvb *dm1105dvb_local; - static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { @@ -414,31 +378,28 @@ static int dm1105dvb_stop_feed(struct dvb_demux_feed *f) return 0; } -/* ir tasklet */ -static void dm1105_emit_key(unsigned long parm) +/* ir work handler */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void dm1105_emit_key(void *parm) +#else +static void dm1105_emit_key(struct work_struct *work) +#endif { - struct infrared *ir = (struct infrared *) parm; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + struct infrared *ir = parm; +#else + struct infrared *ir = container_of(work, struct infrared, work); +#endif u32 ircom = ir->ir_command; u8 data; - u16 keycode; if (ir_debug) printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom); data = (ircom >> 8) & 0x7f; - input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data); - input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); - keycode = ir->key_map[data]; - - if (!keycode) - return; - - input_event(ir->input_dev, EV_KEY, keycode, 1); - input_sync(ir->input_dev); - input_event(ir->input_dev, EV_KEY, keycode, 0); - input_sync(ir->input_dev); - + ir_input_keydown(ir->input_dev, &ir->ir, data, data); + ir_input_nokey(ir->input_dev, &ir->ir); } /* work handler */ @@ -506,34 +467,19 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) break; case INTSTS_IR: dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); - tasklet_schedule(&dm1105dvb->ir.ir_tasklet); + schedule_work(&dm1105dvb->ir.work); break; } return IRQ_HANDLED; } -/* register with input layer */ -static void input_register_keys(struct infrared *ir) -{ - int i; - - memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); - - for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) - set_bit(ir->key_map[i], ir->input_dev->keybit); - - ir->input_dev->keycode = ir->key_map; - ir->input_dev->keycodesize = sizeof(ir->key_map[0]); - ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); -} - int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) { struct input_dev *input_dev; - int err; - - dm1105dvb_local = dm1105; + IR_KEYTAB_TYPE *ir_codes = ir_codes_dm1105_nec; + int ir_type = IR_TYPE_OTHER; + int err = -ENOMEM; input_dev = input_allocate_device(); if (!input_dev) @@ -543,12 +489,11 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), "pci-%s/ir0", pci_name(dm1105->pdev)); - input_dev->evbit[0] = BIT(EV_KEY); + ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes); input_dev->name = "DVB on-card IR receiver"; - input_dev->phys = dm1105->ir.input_phys; input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 2; + input_dev->id.version = 1; if (dm1105->pdev->subsystem_vendor) { input_dev->id.vendor = dm1105->pdev->subsystem_vendor; input_dev->id.product = dm1105->pdev->subsystem_device; @@ -556,25 +501,31 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) input_dev->id.vendor = dm1105->pdev->vendor; input_dev->id.product = dm1105->pdev->device; } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) input_dev->dev.parent = &dm1105->pdev->dev; - /* initial keymap */ - memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map); - input_register_keys(&dm1105->ir); +#else + input_dev->cdev.dev = &dm1105->pdev->dev; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&dm1105->ir.work, dm1105_emit_key, + (unsigned long) &dm1105->ir); +#else + INIT_WORK(&dm1105->ir.work, dm1105_emit_key); +#endif + err = input_register_device(input_dev); if (err) { input_free_device(input_dev); return err; } - tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir); - return 0; } - void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) { - tasklet_kill(&dm1105->ir.ir_tasklet); input_unregister_device(dm1105->ir.input_dev); } -- cgit v1.2.3 From 9c48ff787617a8ab6870134701fa0ee1e7df608e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 26 Feb 2009 16:32:36 -0500 Subject: siano: convert EXPORT_SYMBOL to EXPORT_SYMBOL_GPL From: Michael Krufky As pointed out by Mauro Chehab, we should always use EXPORT_SYMBOL_GPL instead of EXPORT_SYMBOL wherever possible. A message was posted to the linux-media mailing list about this, checking with Uri Shkolnik of Siano Mobile Silicon if this is okay to convert. As per Uri's response to this email, it is OK for us to make this conversion. http://www.spinics.net/lists/linux-media/msg02200.html Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/sms-cards.c | 12 ++++++------ linux/drivers/media/dvb/siano/smscoreapi.c | 30 +++++++++++++++--------------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 44df81a81..66f591937 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -86,7 +86,7 @@ struct sms_board *sms_get_board(int id) return &sms_boards[id]; } -EXPORT_SYMBOL(sms_get_board); +EXPORT_SYMBOL_GPL(sms_get_board); static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) { @@ -139,7 +139,7 @@ int sms_board_setup(struct smscore_device_t *coredev) } return 0; } -EXPORT_SYMBOL(sms_board_setup); +EXPORT_SYMBOL_GPL(sms_board_setup); int sms_board_power(struct smscore_device_t *coredev, int onoff) { @@ -161,7 +161,7 @@ int sms_board_power(struct smscore_device_t *coredev, int onoff) } return 0; } -EXPORT_SYMBOL(sms_board_power); +EXPORT_SYMBOL_GPL(sms_board_power); int sms_board_led_feedback(struct smscore_device_t *coredev, int led) { @@ -184,7 +184,7 @@ int sms_board_led_feedback(struct smscore_device_t *coredev, int led) } return 0; } -EXPORT_SYMBOL(sms_board_led_feedback); +EXPORT_SYMBOL_GPL(sms_board_led_feedback); int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) { @@ -203,7 +203,7 @@ int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) } return -EINVAL; } -EXPORT_SYMBOL(sms_board_lna_control); +EXPORT_SYMBOL_GPL(sms_board_lna_control); int sms_board_load_modules(int id) { @@ -220,4 +220,4 @@ int sms_board_load_modules(int id) } return 0; } -EXPORT_SYMBOL(sms_board_load_modules); +EXPORT_SYMBOL_GPL(sms_board_load_modules); diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 8cb36f540..812b57ab7 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -105,13 +105,13 @@ int smscore_led_state(struct smscore_device_t *core, int led) core->led_state = led; return core->led_state; } -EXPORT_SYMBOL(smscore_set_board_id); +EXPORT_SYMBOL_GPL(smscore_set_board_id); int smscore_get_board_id(struct smscore_device_t *core) { return core->board_id; } -EXPORT_SYMBOL(smscore_get_board_id); +EXPORT_SYMBOL_GPL(smscore_get_board_id); struct smscore_registry_entry_t { struct list_head entry; @@ -172,7 +172,7 @@ int smscore_registry_getmode(char *devpath) return default_mode; } -EXPORT_SYMBOL(smscore_registry_getmode); +EXPORT_SYMBOL_GPL(smscore_registry_getmode); static enum sms_device_type_st smscore_registry_gettype(char *devpath) { @@ -264,7 +264,7 @@ int smscore_register_hotplug(hotplug_t hotplug) return rc; } -EXPORT_SYMBOL(smscore_register_hotplug); +EXPORT_SYMBOL_GPL(smscore_register_hotplug); /** * unregister a client callback that called when device plugged in/unplugged @@ -293,7 +293,7 @@ void smscore_unregister_hotplug(hotplug_t hotplug) kmutex_unlock(&g_smscore_deviceslock); } -EXPORT_SYMBOL(smscore_unregister_hotplug); +EXPORT_SYMBOL_GPL(smscore_unregister_hotplug); static void smscore_notify_clients(struct smscore_device_t *coredev) { @@ -437,7 +437,7 @@ int smscore_register_device(struct smsdevice_params_t *params, return 0; } -EXPORT_SYMBOL(smscore_register_device); +EXPORT_SYMBOL_GPL(smscore_register_device); /** * sets initial device mode and notifies client hotplugs that device is ready @@ -466,7 +466,7 @@ int smscore_start_device(struct smscore_device_t *coredev) return rc; } -EXPORT_SYMBOL(smscore_start_device); +EXPORT_SYMBOL_GPL(smscore_start_device); static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, void *buffer, size_t size, @@ -695,7 +695,7 @@ void smscore_unregister_device(struct smscore_device_t *coredev) sms_info("device %p destroyed", coredev); } -EXPORT_SYMBOL(smscore_unregister_device); +EXPORT_SYMBOL_GPL(smscore_unregister_device); static int smscore_detect_mode(struct smscore_device_t *coredev) { @@ -887,7 +887,7 @@ int smscore_get_device_mode(struct smscore_device_t *coredev) { return coredev->mode; } -EXPORT_SYMBOL(smscore_get_device_mode); +EXPORT_SYMBOL_GPL(smscore_get_device_mode); /** * find client by response id & type within the clients list. @@ -1022,7 +1022,7 @@ void smscore_onresponse(struct smscore_device_t *coredev, smscore_putbuffer(coredev, cb); } } -EXPORT_SYMBOL(smscore_onresponse); +EXPORT_SYMBOL_GPL(smscore_onresponse); /** * return pointer to next free buffer descriptor from core pool @@ -1048,7 +1048,7 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) return cb; } -EXPORT_SYMBOL(smscore_getbuffer); +EXPORT_SYMBOL_GPL(smscore_getbuffer); /** * return buffer descriptor to a pool @@ -1063,7 +1063,7 @@ void smscore_putbuffer(struct smscore_device_t *coredev, { list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); } -EXPORT_SYMBOL(smscore_putbuffer); +EXPORT_SYMBOL_GPL(smscore_putbuffer); static int smscore_validate_client(struct smscore_device_t *coredev, struct smscore_client_t *client, @@ -1143,7 +1143,7 @@ int smscore_register_client(struct smscore_device_t *coredev, return 0; } -EXPORT_SYMBOL(smscore_register_client); +EXPORT_SYMBOL_GPL(smscore_register_client); /** * frees smsclient object and all subclients associated with it @@ -1174,7 +1174,7 @@ void smscore_unregister_client(struct smscore_client_t *client) spin_unlock_irqrestore(&coredev->clientslock, flags); } -EXPORT_SYMBOL(smscore_unregister_client); +EXPORT_SYMBOL_GPL(smscore_unregister_client); /** * verifies that source id is not taken by another client, @@ -1214,7 +1214,7 @@ int smsclient_sendrequest(struct smscore_client_t *client, return coredev->sendrequest_handler(coredev->context, buffer, size); } -EXPORT_SYMBOL(smsclient_sendrequest); +EXPORT_SYMBOL_GPL(smsclient_sendrequest); #if 0 /** -- cgit v1.2.3 From 617a8054280a567b073ab9091ee7255ea803e8c7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Feb 2009 21:16:57 -0300 Subject: v4l2-common: Fix a merge conflict bad solved From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index bc5b40012..a5ce43102 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -589,9 +589,6 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste } EXPORT_SYMBOL(v4l2_ctrl_query_fill); - case V4L2_CID_CAMERA_CLASS: - case V4L2_CID_COLORFX: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and the menu. The qctrl pointer may be NULL, in which case it is ignored. If menu_items is NULL, then the menu items are retrieved using -- cgit v1.2.3 From 9c87709479a0c5cea90c59d8594ddbf012526112 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Feb 2009 21:17:37 -0300 Subject: saa7110: get rid of the legacy v4l2_ctrl_query_fill_std() From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index c417b7007..7c3ad9829 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -339,7 +339,7 @@ static int saa7110_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); default: return -EINVAL; } -- cgit v1.2.3 From 234313d8f7b887f80a2582c6742638d872c5455a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Feb 2009 21:22:18 -0300 Subject: Get rid of video_decoder.h header were uneeded From: Mauro Carvalho Chehab Now, just a few modules are still dependent of this legacy header: $ grep -l DECODER_ `find linux/drivers/media/ -name '*.[ch]' -exec grep -l video_decoder '{}' \;` linux/drivers/media/video/v4l2-ioctl.c linux/drivers/media/video/indycam.c linux/drivers/media/video/saa7191.c linux/drivers/media/video/vino.c Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tvp5150.c | 1 - linux/drivers/media/video/usbvision/usbvision-core.c | 1 - linux/drivers/media/video/usbvision/usbvision-video.c | 1 - 3 files changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index e1046ed3f..9ae372246 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -9,7 +9,6 @@ #include "compat.h" #include #include -#include #include #include #include diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 412149bbe..7fe361668 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index cfa184d63..33d79a5da 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3