From a612e95a5cbca2eaf13c50b9f3900636c166727c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 21 May 2007 13:36:01 -0400 Subject: cx88-blackbird: audio improvements From: Jelle Foks This patch should fix the 'muted audio' and 'raspy audio' problem for mpeg2 streams out of cx88-blackbird devices. Especially mythtv users would find that the audio would often sound bad (aliased, or 'raspy'), mainly related to channel changes, many (all?) other users would find that there was no audio at all in the mpeg data from the encoder chip, unless the audio was manually unmuted. The patch includes the following modifications: Don't actually start the mpeg2 encoder until the device is read from by the application. Wait until the audio is stable for at least 400ms before starting the mpeg encoder. Mute/Unmute the audio when starting/stopping the mpeg encoder. Stop the mpeg encoder when changing parameters and when changing tuner frequency. Add a variable 'mpeg_active' to struct cx8802_dev to allow tracking of whether or not the mpeg2 encoder is active. Load the firmware on cx88-blackbird driver load. Signed-off-by: Jelle Foks Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-blackbird.c | 89 +++++++++++++++++++------ linux/drivers/media/video/cx88/cx88.h | 1 + 2 files changed, 70 insertions(+), 20 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index d9b49275c..8690cad13 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -546,6 +546,9 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) dprintk(1,"Initialize codec\n"); retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { + + dev->mpeg_active = 0; + /* ping was not successful, reset and upload firmware */ cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ msleep(1); @@ -582,38 +585,80 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) blackbird_codec_settings(dev); msleep(1); - /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); - blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); - blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */ blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, BLACKBIRD_FIELD1_SAA7115, BLACKBIRD_FIELD2_SAA7115 ); - /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */ blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - /* initialize the video input */ - blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); - msleep(1); + return 0; +} + +static int blackbird_start_codec(struct file *file, void *priv) +{ + struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; + struct cx88_core *core = dev->core; + /* start capturing to the host interface */ + u32 reg; + + int i; + int lastchange = -1; + int lastval = 0; + + for (i=0; (i < 10) && (i < (lastchange + 4)); i++) + { + reg = cx_read(AUD_STATUS); + + dprintk(1,"AUD_STATUS:%dL: 0x%x\n", i, reg); + if ((reg & 0x0F) != lastval) + { + lastval = reg & 0x0F; + lastchange = i; + } + msleep(100); + } + + /* unmute audio source */ + cx_clear(AUD_VOL_CTL, (1 << 6)); blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); msleep(1); blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); msleep(1); + blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0); + + /* initialize the video input */ + blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); + /* start capturing to the host interface */ - /* blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 0, 0x13); */ blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); msleep(10); - blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0); + dev->mpeg_active = 1; + return 0; +} + +static int blackbird_stop_codec(struct cx8802_dev *dev) +{ + struct cx88_core *core = dev->core; + + blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, + BLACKBIRD_END_NOW, + BLACKBIRD_MPEG_CAPTURE, + BLACKBIRD_RAW_BITS_NONE + ); + /* mute audio source */ + cx_set(AUD_VOL_CTL, (1 << 6)); + + dev->mpeg_active = 0; return 0; } @@ -859,6 +904,10 @@ static int vidioc_s_ext_ctrls (struct file *file, void *priv, if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; + + if (dev->mpeg_active) + blackbird_stop_codec(dev); + p = dev->params; err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS); if (!err) { @@ -890,10 +939,9 @@ static int vidioc_s_frequency (struct file *file, void *priv, struct cx8802_dev *dev = fh->dev; struct cx88_core *core = dev->core; - blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, - BLACKBIRD_END_NOW, - BLACKBIRD_MPEG_CAPTURE, - BLACKBIRD_RAW_BITS_NONE); + if (dev->mpeg_active) + blackbird_stop_codec(dev); + cx88_set_freq (core,f); blackbird_initialize_codec(dev); cx88_set_scale(dev->core, dev->width, dev->height, @@ -1099,15 +1147,11 @@ static int mpeg_open(struct inode *inode, struct file *file) static int mpeg_release(struct inode *inode, struct file *file) { struct cx8802_fh *fh = file->private_data; - struct cx8802_dev *dev = NULL; + struct cx8802_dev *dev = fh->dev; struct cx8802_driver *drv = NULL; - /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ - blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, - BLACKBIRD_END_NOW, - BLACKBIRD_MPEG_CAPTURE, - BLACKBIRD_RAW_BITS_NONE - ); + if (dev->mpeg_active) + blackbird_stop_codec(dev); cx8802_cancel_buffers(fh->dev); /* stop mpeg capture */ @@ -1133,6 +1177,10 @@ static ssize_t mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { struct cx8802_fh *fh = file->private_data; + struct cx8802_dev *dev = fh->dev; + + if (!dev->mpeg_active) + blackbird_start_codec(file, fh); return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0, file->f_flags & O_NONBLOCK); @@ -1311,6 +1359,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) core->name); host_setup(dev->core); + blackbird_initialize_codec(dev); blackbird_register_video(dev); /* initial device configuration: needed ? */ diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 1f294c70d..767bad56a 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -494,6 +494,7 @@ struct cx8802_dev { u32 mailbox; int width; int height; + unsigned char mpeg_active; /* nonzero if mpeg encoder is active */ /* mpeg params */ struct cx2341x_mpeg_params params; -- cgit v1.2.3 From df59e1e030bc294f3e1a9bc01b03361e34b5c013 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 21 May 2007 13:46:06 -0400 Subject: cx88-blackbird: remove unnecessary msleep()'s From: Jelle Foks Remove the unnecessary msleep()'s in cx88-blackbird.c Signed-off-by: Jelle Foks Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-blackbird.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 8690cad13..f0a49f24c 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -551,9 +551,7 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) /* ping was not successful, reset and upload firmware */ cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ - msleep(1); cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ - msleep(1); retval = blackbird_load_firmware(dev); if (retval < 0) return retval; @@ -575,7 +573,6 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) } dprintk(0, "Firmware version is 0x%08x\n", version); } - msleep(1); cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */ cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */ @@ -583,7 +580,6 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */ blackbird_codec_settings(dev); - msleep(1); blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, BLACKBIRD_FIELD1_SAA7115, @@ -594,7 +590,6 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - msleep(1); return 0; } @@ -626,9 +621,7 @@ static int blackbird_start_codec(struct file *file, void *priv) cx_clear(AUD_VOL_CTL, (1 << 6)); blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); - msleep(1); blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); - msleep(1); blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0); @@ -640,7 +633,6 @@ static int blackbird_start_codec(struct file *file, void *priv) BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); - msleep(10); dev->mpeg_active = 1; return 0; -- cgit v1.2.3 From 4534b2fe32a702ee4d2b76c2da7eded605652c8b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 21 May 2007 13:48:58 -0400 Subject: cx88-blackbird: remove unnecessary encoder unmute From: Jelle Foks Remove the unnecessary BLACKBIRD_UNMUTE calls to the mpeg encoder in cx88-blackbird.c The encoder is never muted, hence unmuting should then only be necessary once after hardware initialization. I tested this from warm boots and cold boots (with long power down time to ensure the sram in the chip is emptied), and found that after the firmware upload the encoder is apparently not muted, making the unmutes unnecessary. Signed-off-by: Jelle Foks Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-blackbird.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index f0a49f24c..3cb76e235 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -620,9 +620,6 @@ static int blackbird_start_codec(struct file *file, void *priv) /* unmute audio source */ cx_clear(AUD_VOL_CTL, (1 << 6)); - blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); - blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); - blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0); /* initialize the video input */ -- cgit v1.2.3 From d3fa07b4cb52978d356672273b63a4e4674753fa Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Sun, 30 Sep 2007 17:02:49 +0100 Subject: Audio routes fix for blackbird boards with the wm8775 ADC From: Ricardo Cerqueira Fix lack of audio on the MPEG-2 stream of wm8775 based blackbirds. The wm8775 module initializes the audio input at "route 2", which doesn't hold true for all boards. The HVR-1300, for example, uses route 1 for tuner audio, and route 2 for baseband. So we must route the audio to the proper input depending on what video input is being used. Signed-off-by: Ricardo Cerqueira Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-cards.c | 38 ++++++++++++++--------------- linux/drivers/media/video/cx88/cx88-video.c | 16 ++++++++++-- linux/drivers/media/video/cx88/cx88.h | 2 +- 3 files changed, 34 insertions(+), 22 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 9c76afeb8..ec4133254 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -316,22 +316,22 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x0000bde2, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x0000bde6, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000bde6, - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x0000bd62, - .extadc = 1, + .audioroute = 1, }, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -392,7 +392,7 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, @@ -563,7 +563,7 @@ static const struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .extadc = 1, + .audioroute = 1, }}, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -686,22 +686,22 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x00009d80, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x00009d76, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x00009d76, - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x00009d00, - .extadc = 1, + .audioroute = 1, }, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -840,23 +840,23 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_COMPOSITE1, .vmux = 0, .gpio0 = 0x0000cd73, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 1, .gpio0 = 0x0000cd73, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_TELEVISION, .vmux = 3, .gpio0 = 0x0000cdb3, - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, .vmux = 2, .gpio0 = 0x0000cdf3, - .extadc = 1, + .audioroute = 1, }, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -1124,12 +1124,12 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x3de6, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x3de6, - .extadc = 1, + .audioroute = 1, }}, .radio = { .type = CX88_RADIO, @@ -1386,17 +1386,17 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0xe780, - .extadc = 1, + .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0xe780, - .extadc = 1, + .audioroute = 2, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0xe780, - .extadc = 1, + .audioroute = 2, }}, /* fixme: Add radio support */ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 14b026820..9feb5c4bb 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -410,9 +410,21 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { /* sets sound input from external adc */ - if (INPUT(input).extadc) + if (INPUT(input).audioroute) { + /* The wm8775 module has the "2" route hardwired into + the initialization. Some boards may use different + routes for different inputs. HVR-1300 surely does */ + if (core->board.audio_chip && + core->board.audio_chip == AUDIO_CHIP_WM8775) { + struct v4l2_routing route; + + route.input = INPUT(input).audioroute; + cx88_call_i2c_clients(core, + VIDIOC_INT_S_AUDIO_ROUTING,&route); + } + cx_set(AUD_CTL, EN_I2SIN_ENABLE); - else + } else cx_clear(AUD_CTL, EN_I2SIN_ENABLE); } return 0; diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 767bad56a..b193a26ce 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -231,7 +231,7 @@ struct cx88_input { enum cx88_itype type; u32 gpio0, gpio1, gpio2, gpio3; unsigned int vmux:2; - unsigned int extadc:1; + unsigned int audioroute; }; struct cx88_board { -- cgit v1.2.3 From 7bbfb93108980416344e1851b2d045336540c529 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 13 Oct 2007 19:42:45 -0400 Subject: cx88-blackbird: don't mute audio when stopping the codec From: Michael Krufky We should not mute the audio input when we stop the codec, because it will interfere with the live uncompressed stream. Signed-off-by: Michael Krufky Reviewed-by: Jelle Foks --- linux/drivers/media/video/cx88/cx88-blackbird.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 3cb76e235..d16a3cd72 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -637,15 +637,11 @@ static int blackbird_start_codec(struct file *file, void *priv) static int blackbird_stop_codec(struct cx8802_dev *dev) { - struct cx88_core *core = dev->core; - blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); - /* mute audio source */ - cx_set(AUD_VOL_CTL, (1 << 6)); dev->mpeg_active = 0; return 0; -- cgit v1.2.3 From c085c020a6af7faa8ab0bbf4c010ca9104aa04f0 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Wed, 17 Oct 2007 00:52:08 +0100 Subject: Don't limit cx88 audio routing to blackbird boards From: Ricardo Cerqueira All cx2388 boards need the line-in audio to be routed from an external ADC (refered to as "ADC mode" in the spec sheet), since the chip is uncapable of dealing with baseband audio directly. So... this patch enables normal mode when using the tuner (TV or Radio), and enables ADC mode with any other source. It'll probably only work with boards that have supported ADCs (such as the Wolfson wm9775) Signed-off-by: Ricardo Cerqueira --- linux/drivers/media/video/cx88/cx88-video.c | 46 +++++++++++++++++++---------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 9feb5c4bb..fe6c66a58 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -408,25 +408,41 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) break; } - if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { - /* sets sound input from external adc */ - if (INPUT(input).audioroute) { - /* The wm8775 module has the "2" route hardwired into - the initialization. Some boards may use different - routes for different inputs. HVR-1300 surely does */ - if (core->board.audio_chip && - core->board.audio_chip == AUDIO_CHIP_WM8775) { - struct v4l2_routing route; - - route.input = INPUT(input).audioroute; - cx88_call_i2c_clients(core, - VIDIOC_INT_S_AUDIO_ROUTING,&route); - } + /* if there are audioroutes defined, we have an external + ADC to deal with audio */ + + if (INPUT(input).audioroute) { + + /* cx2388's C-ADC is connected to the tuner only. + When used with S-Video, that ADC is busy dealing with + chroma, so an external must be used for baseband audio */ + if (INPUT(input).type != CX88_VMUX_TELEVISION && + INPUT(input).type != CX88_RADIO) { + /* "ADC mode" */ + cx_write(AUD_I2SCNTL, 0x1); cx_set(AUD_CTL, EN_I2SIN_ENABLE); - } else + } else { + /* Normal mode */ + cx_write(AUD_I2SCNTL, 0x0); cx_clear(AUD_CTL, EN_I2SIN_ENABLE); + } + + /* The wm8775 module has the "2" route hardwired into + the initialization. Some boards may use different + routes for different inputs. HVR-1300 surely does */ + if (core->board.audio_chip && + core->board.audio_chip == AUDIO_CHIP_WM8775) { + struct v4l2_routing route; + + route.input = INPUT(input).audioroute; + cx88_call_i2c_clients(core, + VIDIOC_INT_S_AUDIO_ROUTING,&route); + + } + } + return 0; } EXPORT_SYMBOL(cx88_video_mux); -- cgit v1.2.3 From c89810275c44948f74bf45b42b5057353399bc2e Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Mon, 5 Nov 2007 21:57:11 +0100 Subject: cx88-video: Enable selection of the WM8775 for cx88 cards From: Frej Drejhammar The auto selection of pertinent helper chips (VIDEO_HELPER_CHIPS_AUTO) should select the wm8775 driver, which is used by at least one Conexant 2388x based card (Hauppauge HVR-1300), if VIDEO_CX88 is selected. Signed-off-by: Frej Drejhammar Signed-off-by: Ricardo Cerqueira --- linux/drivers/media/video/cx88/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index ceb31d4a2..49d3813a9 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -8,6 +8,7 @@ config VIDEO_CX88 select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR + select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO ---help--- This is a video4linux driver for Conexant 2388x based TV cards. -- cgit v1.2.3 From 17dadc3798052cea3509d4758b8f08e889a1b7df Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Dec 2007 20:44:54 +0100 Subject: buf-core.c locking fixes From: Adrian Bunk After commit 19fb1457990b6b7e15586ec7331541a184233acc the callers in videobuf-core.c that already hold the lock must call __videobuf_read_start() instead of videobuf_read_start(). Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/videobuf-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c index a85b22147..0758794d0 100644 --- a/linux/drivers/media/video/videobuf-core.c +++ b/linux/drivers/media/video/videobuf-core.c @@ -916,7 +916,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, if (q->streaming) goto done; if (!q->reading) { - retval = videobuf_read_start(q); + retval = __videobuf_read_start(q); if (retval < 0) goto done; } @@ -989,7 +989,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer, stream); } else { if (!q->reading) - videobuf_read_start(q); + __videobuf_read_start(q); if (!q->reading) { rc = POLLERR; } else if (NULL == q->read_buf) { -- cgit v1.2.3 From e957db9edd45ce247ae6eda39c5e0cb07d3230fa Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Wed, 12 Dec 2007 22:22:48 +0100 Subject: media: video: usbvision: add mutex_unlock() to error paths From: Daniel Walker There are a few error paths which don't unlock the usbvision->lock. So I've added mutex_unlock() calls to fix those paths. Signed-off-by: Daniel Walker Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Thierry MERLE --- linux/drivers/media/video/usbvision/usbvision-video.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 04a38c355..92d2a92fd 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1339,6 +1339,7 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) errCode = usbvision_set_alternate(usbvision); if (errCode < 0) { usbvision->last_error = errCode; + mutex_unlock(&usbvision->lock); return -EBUSY; } @@ -1964,6 +1965,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->num_alt,GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { err("usbvision: out of memory!\n"); + mutex_unlock(&usbvision->lock); return -ENOMEM; } -- cgit v1.2.3 From af0e3689d502650b164b118360f25423eb0b1797 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Wed, 12 Dec 2007 22:25:23 +0100 Subject: media-video-usbvision-add-mutex_unlock-to-error-paths-fix From: Andrew Morton Cc: Daniel Walker Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Thierry MERLE --- linux/drivers/media/video/usbvision/usbvision-video.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 92d2a92fd..e0b079baf 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1339,8 +1339,8 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) errCode = usbvision_set_alternate(usbvision); if (errCode < 0) { usbvision->last_error = errCode; - mutex_unlock(&usbvision->lock); - return -EBUSY; + errCode = -EBUSY; + goto out; } // If so far no errors then we shall start the radio @@ -1360,6 +1360,7 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) usbvision->initialized = 0; } } +out: mutex_unlock(&usbvision->lock); return errCode; } -- cgit v1.2.3 From e4be4ca4e052d77fbf7e19b7a88d4da1ad1aa64e Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Wed, 12 Dec 2007 22:37:54 +0100 Subject: media: video: usbvision: remove ctrlUrbLock From: Daniel Walker The ctrlUrbLock has all it's users commented out, and so it's unused. This patch removes it. Signed-off-by: Daniel Walker Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Thierry MERLE --- linux/drivers/media/video/usbvision/usbvision-core.c | 3 --- linux/drivers/media/video/usbvision/usbvision-video.c | 1 - linux/drivers/media/video/usbvision/usbvision.h | 1 - 3 files changed, 5 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 996203969..96fcd5987 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -1611,13 +1611,10 @@ static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, if (len > 8) { return -EFAULT; } -// down(&usbvision->ctrlUrbLock); if (usbvision->ctrlUrbBusy) { -// up(&usbvision->ctrlUrbLock); return -EBUSY; } usbvision->ctrlUrbBusy = 1; -// up(&usbvision->ctrlUrbLock); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) usbvision->ctrlUrbSetup.requesttype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index e0b079baf..385b4709a 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1808,7 +1808,6 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) goto err_exit; } init_waitqueue_head(&usbvision->ctrlUrb_wq); - init_MUTEX(&usbvision->ctrlUrbLock); /* to 1 == available */ usbvision_init_powerOffTimer(usbvision); diff --git a/linux/drivers/media/video/usbvision/usbvision.h b/linux/drivers/media/video/usbvision/usbvision.h index 3b3f1ca0e..9f4c40dbf 100644 --- a/linux/drivers/media/video/usbvision/usbvision.h +++ b/linux/drivers/media/video/usbvision/usbvision.h @@ -373,7 +373,6 @@ struct usb_usbvision { int ctrlUrbBusy; struct usb_ctrlrequest ctrlUrbSetup; wait_queue_head_t ctrlUrb_wq; // Processes waiting - struct semaphore ctrlUrbLock; /* configuration part */ int have_tuner; -- cgit v1.2.3 From d7396992ed278d9d323bcb5bc7dfecd5622d02ea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Dec 2007 22:46:26 -0200 Subject: __videobuf_read_start is static From: Mauro Carvalho Chehab Thanks to Jean Delvare for pointing this. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/videobuf-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c index 0758794d0..1f6f20f46 100644 --- a/linux/drivers/media/video/videobuf-core.c +++ b/linux/drivers/media/video/videobuf-core.c @@ -813,7 +813,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } /* Locking: Caller holds q->lock */ -int __videobuf_read_start(struct videobuf_queue *q) +static int __videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; unsigned long flags = 0; -- cgit v1.2.3 From f1e07f7f29ad59ec31f9ad2e7acd6afb80724a85 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Dec 2007 07:34:12 -0200 Subject: video std is a bitmask. Better to print in hexa From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/videodev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/videodev.c b/linux/drivers/media/video/videodev.c index c3858dc82..7aed73ee4 100644 --- a/linux/drivers/media/video/videodev.c +++ b/linux/drivers/media/video/videodev.c @@ -1010,7 +1010,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, *id = vfd->current_norm; - dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); + dbgarg (cmd, "value=%08Lx\n", (long long unsigned) *id); ret=0; break; @@ -1019,7 +1019,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, { v4l2_std_id *id = arg,norm; - dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); + dbgarg (cmd, "value=%08Lx\n", (long long unsigned) *id); norm = (*id) & vfd->tvnorms; if ( vfd->tvnorms && !norm) /* Check if std is supported */ @@ -1045,7 +1045,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, break; ret=vfd->vidioc_querystd(file, fh, arg); if (!ret) - dbgarg (cmd, "detected std=%Lu\n", + dbgarg (cmd, "detected std=%08Lx\n", (unsigned long long)*p); break; } @@ -1065,7 +1065,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, if (!ret) dbgarg (cmd, "index=%d, name=%s, type=%d, " "audioset=%d, " - "tuner=%d, std=%Ld, status=%d\n", + "tuner=%d, std=%08Lx, status=%d\n", p->index,p->name,p->type,p->audioset, p->tuner, (unsigned long long)p->std, -- cgit v1.2.3 From 9fe6aa61dbfbf8b7dd7570323e9283829201465a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Dec 2007 07:35:26 -0200 Subject: Allow emulating changes of video std by vivi From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vivi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 02e44ab91..521edd1ba 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -992,7 +992,7 @@ static int vidioc_enum_input(struct file *file, void *priv, return -EINVAL; inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_NTSC_M; + inp->std = V4L2_STD_525_60; strcpy(inp->name, "Camera"); return (0); @@ -1245,7 +1245,7 @@ static struct video_device vivi_template = { #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif - .tvnorms = V4L2_STD_NTSC_M, + .tvnorms = V4L2_STD_525_60, .current_norm = V4L2_STD_NTSC_M, }; /* ----------------------------------------------------------------- -- cgit v1.2.3 From e3aa7366ad193f8e6d7db3f89431d63fa635f516 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Dec 2007 07:36:22 -0200 Subject: fix debug enable From: Mauro Carvalho Chehab The changes at vivi_template make debug option to not work properly. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vivi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 521edd1ba..01d5044ca 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -1323,7 +1323,7 @@ MODULE_PARM_DESC(video_nr, "video iminor start number"); module_param(n_devs, int, 0); MODULE_PARM_DESC(n_devs, "number of video devices to create"); -module_param_named(debug, vivi.debug, int, 0644); +module_param_named(debug, vivi_template.debug, int, 0444); MODULE_PARM_DESC(debug, "activates debug info"); module_param(vid_limit, int, 0644); -- cgit v1.2.3 From 9160eb4fb2ca6fbc48ac94cebaafdef6b881ad1b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Dec 2007 14:27:57 -0800 Subject: git-dvb: fix build in drivers/media/dvb/frontends/tda18271.h From: Andrew Morton Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/tda18271.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/tda18271.h b/linux/drivers/media/dvb/frontends/tda18271.h index d84003372..b98a9331c 100644 --- a/linux/drivers/media/dvb/frontends/tda18271.h +++ b/linux/drivers/media/dvb/frontends/tda18271.h @@ -38,7 +38,7 @@ extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, struct i2c_adapter *i2c, - enum tda18271_i2c_gate gate); + enum tda18271_i2c_gate gate) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return NULL; -- cgit v1.2.3 From f91f864ea08f6e0cedb483702194746906519ec4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Dec 2007 14:55:49 -0800 Subject: git-dvb: drivers/media/video/et61x251/et61x251_core.c: fix warnings From: Andrew Morton drivers/media/video/et61x251/et61x251_core.c:390: warning: 'et61x251_i2c_read' defined but not used drivers/media/video/et61x251/et61x251_core.c:397: warning: 'et61x251_i2c_write' defined but not used Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/et61x251/et61x251_core.c | 155 ++++++++++----------- 1 file changed, 77 insertions(+), 78 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/et61x251/et61x251_core.c b/linux/drivers/media/video/et61x251/et61x251_core.c index 43ba5e63d..466e80b7f 100644 --- a/linux/drivers/media/video/et61x251/et61x251_core.c +++ b/linux/drivers/media/video/et61x251/et61x251_core.c @@ -268,72 +268,6 @@ et61x251_i2c_wait(struct et61x251_device* cam, } -static int et61x251_i2c_try_read(struct et61x251_device* cam, - const struct et61x251_sensor* sensor, - u8 address) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - data[0] = address; - data[1] = cam->sensor.i2c_slave_id; - data[2] = cam->sensor.rsta | 0x10; - data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += et61x251_i2c_wait(cam, sensor); - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - if (err) - DBG(3, "I2C read failed for %s image sensor", sensor->name); - - PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]); - - return err ? -1 : (int)data[0]; -} - - -static int et61x251_i2c_try_write(struct et61x251_device* cam, - const struct et61x251_sensor* sensor, - u8 address, u8 value) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - data[0] = address; - data[1] = cam->sensor.i2c_slave_id; - data[2] = cam->sensor.rsta | 0x12; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - data[0] = value; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += et61x251_i2c_wait(cam, sensor); - - if (err) - DBG(3, "I2C write failed for %s image sensor", sensor->name); - - PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value); - - return err ? -1 : 0; -} - - int et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, @@ -386,18 +320,6 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, } -static int et61x251_i2c_read(struct et61x251_device* cam, u8 address) -{ - return et61x251_i2c_try_read(cam, &cam->sensor, address); -} - - -static int et61x251_i2c_write(struct et61x251_device* cam, - u8 address, u8 value) -{ - return et61x251_i2c_try_write(cam, &cam->sensor, address, value); -} - /*****************************************************************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) @@ -679,6 +601,83 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam) /*****************************************************************************/ #ifdef CONFIG_VIDEO_ADV_DEBUG + +static int et61x251_i2c_try_read(struct et61x251_device* cam, + const struct et61x251_sensor* sensor, + u8 address) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = address; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x10; + data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, sensor); + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, + 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + if (err) + DBG(3, "I2C read failed for %s image sensor", sensor->name); + + PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]); + + return err ? -1 : (int)data[0]; +} + + +static int et61x251_i2c_try_write(struct et61x251_device* cam, + const struct et61x251_sensor* sensor, + u8 address, u8 value) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = address; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x12; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + data[0] = value; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, sensor); + + if (err) + DBG(3, "I2C write failed for %s image sensor", sensor->name); + + PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value); + + return err ? -1 : 0; +} + +static int et61x251_i2c_read(struct et61x251_device* cam, u8 address) +{ + return et61x251_i2c_try_read(cam, &cam->sensor, address); +} + +static int et61x251_i2c_write(struct et61x251_device* cam, + u8 address, u8 value) +{ + return et61x251_i2c_try_write(cam, &cam->sensor, address, value); +} + static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) { char str[5]; -- cgit v1.2.3 From b2a759d38e59944cf3c0789068025f0c42b85529 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Dec 2007 19:40:32 +0100 Subject: Makefile: always enter video/ From: Adrian Bunk Since not all code under drivers/media/video/ depends on CONFIG_VIDEO_DEV we cannot only enter it depending on CONFIG_VIDEO_DEV. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/Makefile b/linux/drivers/media/Makefile index 8fa19939c..8cf91353b 100644 --- a/linux/drivers/media/Makefile +++ b/linux/drivers/media/Makefile @@ -3,6 +3,6 @@ # obj-y := common/ -obj-$(CONFIG_VIDEO_DEV) += video/ +obj-y += video/ obj-$(CONFIG_VIDEO_DEV) += radio/ obj-$(CONFIG_DVB_CORE) += dvb/ -- cgit v1.2.3 From 96670291ffbd33cc0cd84ab417e0bb77678bb482 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Dec 2007 14:30:14 -0200 Subject: Fix vivi internal debug messages From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vivi.c | 109 ++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 42 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 01d5044ca..7a38637ec 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -63,7 +63,6 @@ /* Declare static vars that will be used as parameters */ static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ -static struct video_device vivi; /* Video device */ static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ static int n_devs = 1; /* Number of virtual devices */ @@ -119,9 +118,9 @@ static struct v4l2_queryctrl vivi_qctrl[] = { static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; -#define dprintk(level, fmt, arg...) \ +#define dprintk(dev, level, fmt, arg...) \ do { \ - if (vivi.debug >= (level)) \ + if (dev->vfd->debug >= (level)) \ printk(KERN_DEBUG "vivi: " fmt , ## arg); \ } while (0) @@ -355,7 +354,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) dev->timestr); /* FIXME: replacing to __copy_to_user */ if (copy_to_user(vbuf + pos, tmpbuf, wmax * 2) != 0) - dprintk(2, "vivifill copy_to_user failed.\n"); + dprintk(dev, 2, "vivifill copy_to_user failed.\n"); pos += wmax*2; } @@ -384,8 +383,8 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) sprintf(dev->timestr, "%02d:%02d:%02d:%03d", dev->h, dev->m, dev->s, (dev->us + 500) / 1000); - dprintk(2, "vivifill at %s: Buffer 0x%08lx size= %d\n", dev->timestr, - (unsigned long)tmpbuf, pos); + dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n", + dev->timestr, (unsigned long)tmpbuf, pos); /* Advice that buffer was filled */ buf->vb.state = VIDEOBUF_DONE; @@ -409,7 +408,7 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) /* Announces videobuf that all went ok */ for (bc = 0;; bc++) { if (list_empty(&dma_q->active)) { - dprintk(1, "No active queue to serve\n"); + dprintk(dev, 1, "No active queue to serve\n"); break; } @@ -423,7 +422,7 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) } do_gettimeofday(&buf->vb.ts); - dprintk(2, "[%p/%d] wakeup\n", buf, buf->vb. i); + dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); /* Fill buffer */ vivi_fillbuff(dev, buf); @@ -435,16 +434,18 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) } } if (bc != 1) - dprintk(1, "%s: %d buffers handled (should be 1)\n", + dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n", __FUNCTION__, bc); } static void vivi_sleep(struct vivi_dmaqueue *dma_q) { + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); int timeout; DECLARE_WAITQUEUE(wait, current); - dprintk(1, "%s dma_q=0x%08lx\n", __FUNCTION__, (unsigned long)dma_q); + dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__, + (unsigned long)dma_q); add_wait_queue(&dma_q->wq, &wait); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) @@ -471,11 +472,12 @@ static void vivi_sleep(struct vivi_dmaqueue *dma_q) WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) - jiffies; - dprintk(1, "underrun, losed %d frames. " + dprintk(dev, 1, "underrun, losed %d frames. " "Now, frame is %d. Waking on %d jiffies\n", dma_q->frame-old, dma_q->frame, timeout); } else - dprintk(1, "will sleep for %i jiffies\n", timeout); + dprintk(dev, 1, "will sleep for %i jiffies\n", + timeout); vivi_thread_tick(dma_q); @@ -489,6 +491,7 @@ static void vivi_sleep(struct vivi_dmaqueue *dma_q) static int vivi_thread(void *data) { struct vivi_dmaqueue *dma_q = data; + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) daemonize(); @@ -504,7 +507,7 @@ static int vivi_thread(void *data) if (dma_q->notify != NULL) up(dma_q->notify); #endif - dprintk(1, "thread started\n"); + dprintk(dev, 1, "thread started\n"); mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); set_freezable(); @@ -519,7 +522,7 @@ static int vivi_thread(void *data) #endif break; } - dprintk(1, "thread: exit\n"); + dprintk(dev, 1, "thread: exit\n"); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) dma_q->kthread = NULL; @@ -531,10 +534,12 @@ static int vivi_thread(void *data) static int vivi_start_thread(struct vivi_dmaqueue *dma_q) { + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + dma_q->frame = 0; dma_q->ini_jiffies = jiffies; - dprintk(1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __FUNCTION__); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi"); @@ -561,13 +566,15 @@ static int vivi_start_thread(struct vivi_dmaqueue *dma_q) /* Wakes thread */ wake_up_interruptible(&dma_q->wq); - dprintk(1, "returning from %s\n", __FUNCTION__); + dprintk(dev, 1, "returning from %s\n", __FUNCTION__); return 0; } static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) { - dprintk(1, "%s\n", __FUNCTION__); + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + + dprintk(dev, 1, "%s\n", __FUNCTION__); /* shutdown control thread */ if (dma_q->kthread) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) @@ -589,17 +596,19 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) static int restart_video_queue(struct vivi_dmaqueue *dma_q) { + struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); struct vivi_buffer *buf, *prev; - dprintk(1, "%s dma_q=0x%08lx\n", __FUNCTION__, (unsigned long)dma_q); + dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__, + (unsigned long)dma_q); if (!list_empty(&dma_q->active)) { buf = list_entry(dma_q->active.next, struct vivi_buffer, vb.queue); - dprintk(2, "restart_queue [%p/%d]: restart dma\n", + dprintk(dev, 2, "restart_queue [%p/%d]: restart dma\n", buf, buf->vb.i); - dprintk(1, "Restarting video dma\n"); + dprintk(dev, 1, "Restarting video dma\n"); vivi_stop_thread(dma_q); /* cancel all outstanding capture / vbi requests */ @@ -623,13 +632,14 @@ static int restart_video_queue(struct vivi_dmaqueue *dma_q) list_del(&buf->vb.queue); list_add_tail(&buf->vb.queue, &dma_q->active); - dprintk(1, "Restarting video dma\n"); + dprintk(dev, 1, "Restarting video dma\n"); vivi_stop_thread(dma_q); vivi_start_thread(dma_q); buf->vb.state = VIDEOBUF_ACTIVE; mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] restart_queue - first active\n", + dprintk(dev, 2, + "[%p/%d] restart_queue - first active\n", buf, buf->vb.i); } else if (prev->vb.width == buf->vb.width && @@ -638,7 +648,8 @@ static int restart_video_queue(struct vivi_dmaqueue *dma_q) list_del(&buf->vb.queue); list_add_tail(&buf->vb.queue, &dma_q->active); buf->vb.state = VIDEOBUF_ACTIVE; - dprintk(2, "[%p/%d] restart_queue - move to active\n", + dprintk(dev, 2, + "[%p/%d] restart_queue - move to active\n", buf, buf->vb.i); } else { return 0; @@ -671,7 +682,8 @@ static void vivi_vid_timeout(unsigned long data) static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { - struct vivi_fh *fh = vq->priv_data; + struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = fh->dev; *size = fh->width*fh->height*2; @@ -681,14 +693,18 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) while (*size * *count > vid_limit * 1024 * 1024) (*count)--; - dprintk(1, "%s, count=%d, size=%d\n", __FUNCTION__, *count, *size); + dprintk(dev, 1, "%s, count=%d, size=%d\n", __FUNCTION__, + *count, *size); return 0; } static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) { - dprintk(1, "%s\n", __FUNCTION__); + struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = fh->dev; + + dprintk(dev, 1, "%s\n", __FUNCTION__); if (in_interrupt()) BUG(); @@ -705,10 +721,11 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) { struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = fh->dev; struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); int rc, init_buffer = 0; - dprintk(1, "%s, field=%d\n", __FUNCTION__, field); + dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field); BUG_ON(NULL == fh->fmt); if (fh->width < 48 || fh->width > norm_maxw() || @@ -754,18 +771,18 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) struct vivi_buffer *prev; if (!list_empty(&vidq->queued)) { - dprintk(1, "adding vb queue=0x%08lx\n", + dprintk(dev, 1, "adding vb queue=0x%08lx\n", (unsigned long)&buf->vb.queue); list_add_tail(&buf->vb.queue, &vidq->queued); buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", + dprintk(dev, 2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&vidq->active)) { list_add_tail(&buf->vb.queue, &vidq->active); buf->vb.state = VIDEOBUF_ACTIVE; mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active\n", + dprintk(dev, 2, "[%p/%d] buffer_queue - first active\n", buf, buf->vb.i); vivi_start_thread(vidq); @@ -777,13 +794,15 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) prev->fmt == buf->fmt) { list_add_tail(&buf->vb.queue, &vidq->active); buf->vb.state = VIDEOBUF_ACTIVE; - dprintk(2, "[%p/%d] buffer_queue - append to active\n", + dprintk(dev, 2, + "[%p/%d] buffer_queue - append to active\n", buf, buf->vb.i); } else { list_add_tail(&buf->vb.queue, &vidq->queued); buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", + dprintk(dev, 2, + "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); } } @@ -797,7 +816,7 @@ static void buffer_release(struct videobuf_queue *vq, struct vivi_dev *dev = (struct vivi_dev *)fh->dev; struct vivi_dmaqueue *vidq = &dev->vidq; - dprintk(1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __FUNCTION__); vivi_stop_thread(vidq); @@ -857,13 +876,16 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv, static int vidioc_try_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; struct vivi_fmt *fmt; enum v4l2_field field; unsigned int maxw, maxh; if (format.fourcc != f->fmt.pix.pixelformat) { - dprintk(1, "Fourcc format (0x%08x) invalid. Driver accepts " - "only 0x%08x\n", f->fmt.pix.pixelformat, format.fourcc); + dprintk(dev, 1, "Fourcc format (0x%08x) invalid. " + "Driver accepts only 0x%08x\n", + f->fmt.pix.pixelformat, format.fourcc); return -EINVAL; } fmt = &format; @@ -873,7 +895,7 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv, if (field == V4L2_FIELD_ANY) { field = V4L2_FIELD_INTERLACED; } else if (V4L2_FIELD_INTERLACED != field) { - dprintk(1, "Field type invalid.\n"); + dprintk(dev, 1, "Field type invalid.\n"); return -EINVAL; } @@ -1082,7 +1104,7 @@ found: /* If more than one user, mutex should be added */ dev->users++; - dprintk(1, "open minor=%d type=%s users=%d\n", minor, + dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor, v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); /* allocate + initialize per filehandle data */ @@ -1137,9 +1159,10 @@ static unsigned int vivi_poll(struct file *file, struct poll_table_struct *wait) { struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; struct videobuf_queue *q = &fh->vb_vidq; - dprintk(1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __FUNCTION__); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) return POLLERR; @@ -1163,7 +1186,8 @@ static int vivi_close(struct inode *inode, struct file *file) dev->users--; - dprintk(1, "close called (minor=%d, users=%d)\n", minor, dev->users); + dprintk(dev, 1, "close called (minor=%d, users=%d)\n", + minor, dev->users); return 0; } @@ -1191,14 +1215,15 @@ static int vivi_release(void) static int vivi_mmap(struct file *file, struct vm_area_struct *vma) { - struct vivi_fh *fh = file->private_data; + struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; int ret; - dprintk(1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); + dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); - dprintk(1, "vma start=0x%08lx, size=%ld, ret=%d\n", + dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", (unsigned long)vma->vm_start, (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, ret); -- cgit v1.2.3 From 73496c4df0fd7d4a818bccfcd1f99fdd0958d82e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Dec 2007 17:13:37 -0200 Subject: Add proper locking for buffer filling From: Mauro Carvalho Chehab Avoids de-alocating buffers before finishing to fill a buffer Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vivi.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 7a38637ec..66826c0f1 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -180,6 +180,7 @@ struct vivi_dev { #else struct semaphore lock; #endif + spinlock_t slock; int users; @@ -405,6 +406,7 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) int bc; + spin_lock(&dev->slock); /* Announces videobuf that all went ok */ for (bc = 0;; bc++) { if (list_empty(&dma_q->active)) { @@ -418,6 +420,7 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) /* Nobody is waiting something to be done, just return */ if (!waitqueue_active(&buf->vb.done)) { mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + spin_unlock(&dev->slock); return; } @@ -436,6 +439,7 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) if (bc != 1) dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n", __FUNCTION__, bc); + spin_unlock(&dev->slock); } static void vivi_sleep(struct vivi_dmaqueue *dma_q) @@ -664,6 +668,8 @@ static void vivi_vid_timeout(unsigned long data) struct vivi_dmaqueue *vidq = &dev->vidq; struct vivi_buffer *buf; + spin_lock(&dev->slock); + while (!list_empty(&vidq->active)) { buf = list_entry(vidq->active.next, struct vivi_buffer, vb.queue); @@ -672,8 +678,9 @@ static void vivi_vid_timeout(unsigned long data) wake_up(&buf->vb.done); printk(KERN_INFO "vivi/0: [%p/%d] timeout\n", buf, buf->vb.i); } - restart_video_queue(vidq); + + spin_unlock(&dev->slock); } /* ------------------------------------------------------------------ @@ -1137,7 +1144,7 @@ found: dev->h, dev->m, dev->s, (dev->us + 500) / 1000); videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops, - NULL, NULL, fh->type, V4L2_FIELD_INTERLACED, + NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, sizeof(struct vivi_buffer), fh); return 0; @@ -1297,6 +1304,7 @@ static int __init vivi_init(void) /* initialize locks */ mutex_init(&dev->lock); + spin_lock_init(&dev->slock); dev->vidq.timeout.function = vivi_vid_timeout; dev->vidq.timeout.data = (unsigned long)dev; -- cgit v1.2.3 From e5495a700e69283077b0f9e773c65bb099094d01 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Dec 2007 17:15:41 -0200 Subject: Cleanup kernel thread and provide overrun detection From: Mauro Carvalho Chehab The previous code were a little bit messy. Cleans it up. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vivi.c | 76 +++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 33 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 66826c0f1..0305589d1 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -442,10 +442,13 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) spin_unlock(&dev->slock); } +#define frames_to_ms(frames) \ + ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) + static void vivi_sleep(struct vivi_dmaqueue *dma_q) { struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); - int timeout; + int timeout, running_time; DECLARE_WAITQUEUE(wait, current); dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__, @@ -453,41 +456,48 @@ static void vivi_sleep(struct vivi_dmaqueue *dma_q) add_wait_queue(&dma_q->wq, &wait); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) - if (!(q->rmmod || signal_pending(current))) { + if ((q->rmmod || signal_pending(current))) + goto stop_task; #else - if (!kthread_should_stop()) { + if (kthread_should_stop()) + goto stop_task; #endif - dma_q->frame++; - - /* Calculate time to wake up */ - timeout = dma_q->ini_jiffies+ - msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR * 1000) - / WAKE_DENOMINATOR) - jiffies; - - if (timeout <= 0) { - int old = dma_q->frame; - dma_q->frame = (jiffies_to_msecs(jiffies - - dma_q->ini_jiffies) * - WAKE_DENOMINATOR) / - (WAKE_NUMERATOR * 1000) + 1; - - timeout = dma_q->ini_jiffies+ - msecs_to_jiffies((dma_q->frame * - WAKE_NUMERATOR * 1000) - / WAKE_DENOMINATOR) - jiffies; - - dprintk(dev, 1, "underrun, losed %d frames. " - "Now, frame is %d. Waking on %d jiffies\n", - dma_q->frame-old, dma_q->frame, timeout); - } else - dprintk(dev, 1, "will sleep for %i jiffies\n", - timeout); - - vivi_thread_tick(dma_q); - - schedule_timeout_interruptible(timeout); - } + running_time = jiffies - dma_q->ini_jiffies; + dma_q->frame++; + + /* Calculate time to wake up */ + timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - running_time; + + if (timeout > msecs_to_jiffies(frames_to_ms(2)) || timeout <= 0) { + int old = dma_q->frame; + int nframes; + + dma_q->frame = (jiffies_to_msecs(running_time) / + frames_to_ms(1)) + 1; + + timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) + - running_time; + + if (unlikely (timeout <= 0)) + timeout = 1; + + nframes = (dma_q->frame > old)? + dma_q->frame - old : old - dma_q->frame; + + dprintk(dev, 1, "%ld: %s %d frames. " + "Current frame is %d. Will sleep for %d jiffies\n", + jiffies, + (dma_q->frame > old)? "Underrun, losed" : "Overrun of", + nframes, dma_q->frame, timeout); + } else + dprintk(dev, 1, "will sleep for %d jiffies\n", timeout); + + vivi_thread_tick(dma_q); + + schedule_timeout_interruptible(timeout); + +stop_task: remove_wait_queue(&dma_q->wq, &wait); try_to_freeze(); } -- cgit v1.2.3 From 0e33cee5e160ae0638795ac4157df047a3647e8a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Dec 2007 16:43:57 -0800 Subject: git-dvb: drivers/media/dvb/frontends/zl10353.c: avoid 64-bit divide From: Andrew Morton Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/zl10353.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index 276612e00..bc8e7b0f5 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -149,7 +149,8 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe, break; } - value = (bw * (u64)10 * (1 << 23) / 7 * 125 + adc_clock / 2); + value = (u64)10 * (1 << 23) / 7 * 125; + value = (bw * value) + adc_clock / 2; do_div(value, adc_clock); *nominal_rate = value; -- cgit v1.2.3 From 359077037af7b20f69cde8ff021e4f5f89e4922f Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Wed, 12 Dec 2007 20:14:00 -0500 Subject: s5h1409: QAM SNR related fixes From: Steven Toth QAM SNR values were incorrect when the cable was disconnected. This patch extends the lookup tables to ensure correct values are being returned. Signed-off-by: Steven Toth Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/s5h1409.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c index 188bcb247..b8679cf7a 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.c +++ b/linux/drivers/media/dvb/frontends/s5h1409.c @@ -107,7 +107,7 @@ static struct vsb_snr_tab { u16 val; u16 data; } vsb_snr_tab[] = { - { 1023, 770, }, + { 924, 300, }, { 923, 300, }, { 918, 295, }, { 915, 290, }, @@ -154,6 +154,7 @@ static struct qam64_snr_tab { u16 val; u16 data; } qam64_snr_tab[] = { + { 1, 0, }, { 12, 300, }, { 15, 290, }, { 18, 280, }, @@ -217,6 +218,7 @@ static struct qam64_snr_tab { { 95, 202, }, { 96, 201, }, { 104, 200, }, + { 255, 0, }, }; /* QAM256 SNR lookup table */ @@ -224,6 +226,7 @@ static struct qam256_snr_tab { u16 val; u16 data; } qam256_snr_tab[] = { + { 1, 0, }, { 12, 400, }, { 13, 390, }, { 15, 380, }, @@ -292,6 +295,7 @@ static struct qam256_snr_tab { { 105, 262, }, { 106, 261, }, { 110, 260, }, + { 255, 0, }, }; /* 8 bit registers, 16 bit values */ @@ -670,14 +674,15 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr) u16 reg; dprintk("%s()\n", __FUNCTION__); - reg = s5h1409_readreg(state, 0xf1) & 0x1ff; - switch(state->current_modulation) { case QAM_64: + reg = s5h1409_readreg(state, 0xf0) & 0xff; return s5h1409_qam64_lookup_snr(fe, snr, reg); case QAM_256: + reg = s5h1409_readreg(state, 0xf0) & 0xff; return s5h1409_qam256_lookup_snr(fe, snr, reg); case VSB_8: + reg = s5h1409_readreg(state, 0xf1) & 0x3ff; return s5h1409_vsb_lookup_snr(fe, snr, reg); default: break; -- cgit v1.2.3 From 3ba8b535d2a607ac624f4c7d5cdab9187514c747 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Dec 2007 21:30:26 -0800 Subject: i2c: fix drivers/media/video/bt866.c From: Andrew Morton usage_count got removed. Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt866.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index 1f9efb8b3..89161e867 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -301,7 +301,6 @@ static struct i2c_client bt866_client_tmpl = .addr = 0, .adapter = NULL, .driver = &i2c_driver_bt866, - .usage_count = 0 }; static int bt866_found_proc(struct i2c_adapter *adapter, -- cgit v1.2.3 From 32127f7d5133a71be9aadd4f6c8275ff3fd4a7e9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 13 Dec 2007 08:04:10 -0500 Subject: s5h1409: fix IF frequency configuration From: Michael Krufky On the s5h1409 demod, the IF frequency for VSB is limited to 44 / 5.38 MHz. Hardcode VSB IF frequency within the driver to 44 / 5.38 MHz. QAM IF frequency remains configurable via attach-time configuration. Acked-by: Steven Toth Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/s5h1409.c | 14 +++++++++++++- linux/drivers/media/dvb/frontends/s5h1409.h | 4 ++-- linux/drivers/media/video/cx23885/cx23885-dvb.c | 4 ++-- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c index b8679cf7a..f11827927 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.c +++ b/linux/drivers/media/dvb/frontends/s5h1409.c @@ -42,6 +42,7 @@ struct s5h1409_state { fe_modulation_t current_modulation; u32 current_frequency; + int if_freq; u32 is_qam_locked; u32 qam_state; @@ -348,6 +349,9 @@ static int s5h1409_softreset(struct dvb_frontend* fe) return 0; } +#define S5H1409_VSB_IF_FREQ 5380 +#define S5H1409_QAM_IF_FREQ state->config->qam_if + static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz) { struct s5h1409_state* state = fe->demodulator_priv; @@ -369,6 +373,9 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz) ret = -1; } + if (0 == ret) + state->if_freq = KHz; + return ret; } @@ -394,11 +401,15 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe, switch(m) { case VSB_8: dprintk("%s() VSB_8\n", __FUNCTION__); + if (state->if_freq != S5H1409_VSB_IF_FREQ) + s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ); s5h1409_writereg(state, 0xf4, 0); break; case QAM_64: case QAM_256: dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__); + if (state->if_freq != S5H1409_QAM_IF_FREQ) + s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ); s5h1409_writereg(state, 0xf4, 1); s5h1409_writereg(state, 0x85, 0x110); break; @@ -571,7 +582,7 @@ static int s5h1409_init (struct dvb_frontend* fe) s5h1409_writereg(state, 0xab, 0x0); /* Parallel */ s5h1409_set_spectralinversion(fe, state->config->inversion); - s5h1409_set_if_freq(fe, state->config->if_freq); + s5h1409_set_if_freq(fe, state->if_freq); s5h1409_set_gpio(fe, state->config->gpio); s5h1409_softreset(fe); @@ -751,6 +762,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, state->config = config; state->i2c = i2c; state->current_modulation = 0; + state->if_freq = S5H1409_VSB_IF_FREQ; /* check if the demod exists */ if (s5h1409_readreg(state, 0x04) != 0x0066) diff --git a/linux/drivers/media/dvb/frontends/s5h1409.h b/linux/drivers/media/dvb/frontends/s5h1409.h index 20f9af1af..b1f433906 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.h +++ b/linux/drivers/media/dvb/frontends/s5h1409.h @@ -39,8 +39,8 @@ struct s5h1409_config #define S5H1409_GPIO_ON 1 u8 gpio; - /* IF Freq in KHz */ - u16 if_freq; + /* IF Freq for QAM in KHz, VSB is hardcoded to 5380 */ + u16 qam_if; /* Spectral Inversion */ #define S5H1409_INVERSION_OFF 0 diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index c21d21511..36e5dd22a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -86,7 +86,7 @@ static struct s5h1409_config hauppauge_generic_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, .gpio = S5H1409_GPIO_ON, - .if_freq = 44000, + .qam_if = 44000, .inversion = S5H1409_INVERSION_OFF, .status_mode = S5H1409_DEMODLOCKING }; @@ -95,7 +95,7 @@ static struct s5h1409_config hauppauge_hvr1800lp_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, .gpio = S5H1409_GPIO_OFF, - .if_freq = 44000, + .qam_if = 44000, .inversion = S5H1409_INVERSION_OFF, .status_mode = S5H1409_DEMODLOCKING }; -- cgit v1.2.3 From ae5e0bd6101a2b5eed55d740487c8d30f837907f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 13 Dec 2007 08:11:49 -0500 Subject: s5h1409: use VSB IF frequency ( 44 / 5.38 MHz ) unless otherwise specified From: Michael Krufky use VSB IF frequency ( 44 / 5.38 MHz ) if qam_if is invalid or unspecified Acked-by: Steven Toth Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/s5h1409.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c index f11827927..29ec9ac8f 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.c +++ b/linux/drivers/media/dvb/frontends/s5h1409.c @@ -355,28 +355,26 @@ static int s5h1409_softreset(struct dvb_frontend* fe) static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz) { struct s5h1409_state* state = fe->demodulator_priv; - int ret = 0; dprintk("%s(%d KHz)\n", __FUNCTION__, KHz); - if( (KHz == 44000) || (KHz == 5380) ) { - s5h1409_writereg(state, 0x87, 0x01be); - s5h1409_writereg(state, 0x88, 0x0436); - s5h1409_writereg(state, 0x89, 0x054d); - } else - if (KHz == 4000) { + switch (KHz) { + case 4000: s5h1409_writereg(state, 0x87, 0x014b); s5h1409_writereg(state, 0x88, 0x0cb5); s5h1409_writereg(state, 0x89, 0x03e2); - } else { - printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz); - ret = -1; + break; + case 5380: + case 44000: + default: + s5h1409_writereg(state, 0x87, 0x01be); + s5h1409_writereg(state, 0x88, 0x0436); + s5h1409_writereg(state, 0x89, 0x054d); + break; } + state->if_freq = KHz; - if (0 == ret) - state->if_freq = KHz; - - return ret; + return 0; } static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted) -- cgit v1.2.3 From d2e3737abe8054b9eddb05605fa8ce035e102dac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 16 Dec 2007 10:24:30 -0200 Subject: Auto-selects D2633 for ATSC From: Mauro Carvalho Chehab ATSC standard-specific firmware is D2633 on both v2.5 and v2.7. Better to auto-select this firmware, overriding ctrl.d2633. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 745673be6..29c5faf62 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -985,7 +985,10 @@ static int xc2028_set_params(struct dvb_frontend *fe, break; case FE_ATSC: bw = BANDWIDTH_6_MHZ; + /* The only ATSC firmware (at least on v2.7) is D2633, + so overrides ctrl->d2633 */ type |= ATSC| D2633; + type &= ~D2620; break; /* DVB-S is not supported */ default: -- cgit v1.2.3 From 0dd5f9acbc4f69e168833c43267d3c3ca74d7a25 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Dec 2007 17:14:31 -0500 Subject: tda9887: remove references to struct tuner from printk macros From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/video/tda9887.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index bd4173e41..f262055c9 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -29,14 +29,14 @@ static int tda9887_debug; module_param_named(debug, tda9887_debug, int, 0644); #define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \ - i2c_adapter_id(priv->t->i2c->adapter), \ - priv->t->i2c->addr, ##arg); } while (0) + printk(KERN_INFO "tda9887 %d-%04x: " fmt, \ + i2c_adapter_id(priv->i2c_props.adap), \ + priv->i2c_props.addr, ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (tda9887_debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \ - i2c_adapter_id(priv->t->i2c->adapter), \ - priv->t->i2c->addr, ##arg); } while (0) + printk(KERN_INFO "tda9887 %d-%04x: " fmt, \ + i2c_adapter_id(priv->i2c_props.adap), \ + priv->i2c_props.addr, ##arg); } while (0) struct tda9887_priv { struct tuner_i2c_props i2c_props; -- cgit v1.2.3 From 72459008a1643c4804ee6688426d7c29a66a545b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Dec 2007 17:27:23 -0500 Subject: tuner: add set_config to struct analog_tuner_ops From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/video/tuner-core.c | 14 ++++++++++++++ linux/drivers/media/video/tuner-driver.h | 3 +++ 2 files changed, 17 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 479afb1f6..47aafed34 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -183,6 +183,19 @@ static int fe_has_signal(struct dvb_frontend *fe) return strength; } +static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg) +{ + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; + struct tuner *t = fe->analog_demod_priv; + + if (fe_tuner_ops->set_config) + return fe_tuner_ops->set_config(fe, priv_cfg); + + tuner_warn("Tuner frontend module has no way to set config\n"); + + return 0; +} + static void tuner_status(struct dvb_frontend *fe); static struct analog_tuner_ops tuner_core_ops = { @@ -190,6 +203,7 @@ static struct analog_tuner_ops tuner_core_ops = { .standby = fe_standby, .release = fe_release, .has_signal = fe_has_signal, + .set_config = fe_set_config, .tuner_status = tuner_status }; diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 65ced4350..7f43dc68a 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -45,6 +45,9 @@ struct analog_tuner_ops { void (*standby)(struct dvb_frontend *fe); void (*release)(struct dvb_frontend *fe); int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable); + + /** This is to allow setting tuner-specific configuration */ + int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); }; struct tuner { -- cgit v1.2.3 From e204914b6924b0eda3d4a8adbe8334c5ed27d457 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Dec 2007 17:53:32 -0500 Subject: tuner: convert tda9887 to use TUNER_SET_CONFIG From: Michael Krufky Use TUNER_SET_CONFIG to set configuration in tda9887's private state structure, rather than storing tda9887-specific configuration within struct tuner. Update handling of TUNER_SET_CONFIG by tuner-core, to call &t->fe.ops.analog_demod_ops rather than &t->fe.ops.tuner_ops analog_demod_ops.set_config passes the request to tuner_ops.set_config, so this does not break other drivers. Signed-off-by: Michael Krufky --- linux/drivers/media/video/tda9887.c | 47 ++++++++++++++++++++------------ linux/drivers/media/video/tuner-core.c | 12 ++------ linux/drivers/media/video/tuner-driver.h | 3 -- 3 files changed, 33 insertions(+), 29 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index f262055c9..77e40d0ec 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -42,6 +42,7 @@ struct tda9887_priv { struct tuner_i2c_props i2c_props; unsigned char data[4]; + unsigned int config; struct tuner *t; }; @@ -484,31 +485,31 @@ static int tda9887_set_insmod(struct dvb_frontend *fe) return 0; } -static int tda9887_set_config(struct dvb_frontend *fe) +static int tda9887_do_config(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; struct tuner *t = priv->t; char *buf = priv->data; - if (t->tda9887_config & TDA9887_PORT1_ACTIVE) + if (priv->config & TDA9887_PORT1_ACTIVE) buf[1] &= ~cOutputPort1Inactive; - if (t->tda9887_config & TDA9887_PORT1_INACTIVE) + if (priv->config & TDA9887_PORT1_INACTIVE) buf[1] |= cOutputPort1Inactive; - if (t->tda9887_config & TDA9887_PORT2_ACTIVE) + if (priv->config & TDA9887_PORT2_ACTIVE) buf[1] &= ~cOutputPort2Inactive; - if (t->tda9887_config & TDA9887_PORT2_INACTIVE) + if (priv->config & TDA9887_PORT2_INACTIVE) buf[1] |= cOutputPort2Inactive; - if (t->tda9887_config & TDA9887_QSS) + if (priv->config & TDA9887_QSS) buf[1] |= cQSS; - if (t->tda9887_config & TDA9887_INTERCARRIER) + if (priv->config & TDA9887_INTERCARRIER) buf[1] &= ~cQSS; - if (t->tda9887_config & TDA9887_AUTOMUTE) + if (priv->config & TDA9887_AUTOMUTE) buf[1] |= cAutoMuteFmActive; - if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { + if (priv->config & TDA9887_DEEMPHASIS_MASK) { buf[2] &= ~0x60; - switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { + switch (priv->config & TDA9887_DEEMPHASIS_MASK) { case TDA9887_DEEMPHASIS_NONE: buf[2] |= cDeemphasisOFF; break; @@ -520,21 +521,22 @@ static int tda9887_set_config(struct dvb_frontend *fe) break; } } - if (t->tda9887_config & TDA9887_TOP_SET) { + if (priv->config & TDA9887_TOP_SET) { buf[2] &= ~cTopMask; - buf[2] |= (t->tda9887_config >> 8) & cTopMask; + buf[2] |= (priv->config >> 8) & cTopMask; } - if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) + if ((priv->config & TDA9887_INTERCARRIER_NTSC) && + (t->std & V4L2_STD_NTSC)) buf[1] &= ~cQSS; - if (t->tda9887_config & TDA9887_GATING_18) + if (priv->config & TDA9887_GATING_18) buf[3] &= ~cGating_36; if (t->mode == V4L2_TUNER_RADIO) { - if (t->tda9887_config & TDA9887_RIF_41_3) { + if (priv->config & TDA9887_RIF_41_3) { buf[3] &= ~cVideoIFMask; buf[3] |= cRadioIF_41_30; } - if (t->tda9887_config & TDA9887_GAIN_NORMAL) + if (priv->config & TDA9887_GAIN_NORMAL) buf[3] &= ~cTunerGainLow; } @@ -581,7 +583,7 @@ static void tda9887_configure(struct dvb_frontend *fe) priv->data[1] |= cOutputPort1Inactive; priv->data[1] |= cOutputPort2Inactive; - tda9887_set_config(fe); + tda9887_do_config(fe); tda9887_set_insmod(fe); if (t->mode == T_STANDBY) { @@ -640,6 +642,16 @@ static void tda9887_set_params(struct dvb_frontend *fe, tda9887_configure(fe); } +static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg) +{ + struct tda9887_priv *priv = fe->analog_demod_priv; + + priv->config = *(unsigned int *)priv_cfg; + tda9887_configure(fe); + + return 0; +} + static void tda9887_release(struct dvb_frontend *fe) { kfree(fe->analog_demod_priv); @@ -655,6 +667,7 @@ static struct analog_tuner_ops tda9887_tuner_ops = { .tuner_status = tda9887_tuner_status, .get_afc = tda9887_get_afc, .release = tda9887_release, + .set_config = tda9887_set_config, }; int tda9887_attach(struct tuner *t) diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 47aafed34..5b5a38eaf 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -877,25 +877,19 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) #endif case TUNER_SET_CONFIG: { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; struct v4l2_priv_tun_config *cfg = arg; if (t->type != cfg->tuner) break; - if (t->type == TUNER_TDA9887) { - t->tda9887_config = *(unsigned int *)cfg->priv; - set_freq(client, t->tv_freq); - break; - } - - if (NULL == fe_tuner_ops->set_config) { + if ((NULL == ops) || (NULL == ops->set_config)) { tuner_warn("Tuner frontend module has no way to " "set config\n"); break; } - fe_tuner_ops->set_config(&t->fe, cfg->priv); + ops->set_config(&t->fe, cfg->priv); break; } /* --- v4l ioctls --- */ diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 7f43dc68a..417753b7c 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -69,9 +69,6 @@ struct tuner { struct dvb_frontend fe; - /* used by tda9887 */ - unsigned int tda9887_config; - unsigned int config; int (*tuner_callback) (void *dev, int command,int arg); }; -- cgit v1.2.3 From ebba1f853c5fce4cb1921b1b1c976aa7861f4594 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Dec 2007 18:05:00 -0500 Subject: tda9887: maintain private state independent of struct tuner From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/video/tda9887.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 77e40d0ec..039afe418 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -43,8 +43,9 @@ struct tda9887_priv { unsigned char data[4]; unsigned int config; - - struct tuner *t; + unsigned int mode; + unsigned int audmode; + v4l2_std_id std; }; /* ---------------------------------------------------------------------- */ @@ -406,19 +407,18 @@ static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) static int tda9887_set_tvnorm(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; struct tvnorm *norm = NULL; char *buf = priv->data; int i; - if (t->mode == V4L2_TUNER_RADIO) { - if (t->audmode == V4L2_TUNER_MODE_MONO) + if (priv->mode == V4L2_TUNER_RADIO) { + if (priv->audmode == V4L2_TUNER_MODE_MONO) norm = &radio_mono; else norm = &radio_stereo; } else { for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { - if (tvnorms[i].std & t->std) { + if (tvnorms[i].std & priv->std) { norm = tvnorms+i; break; } @@ -488,7 +488,6 @@ static int tda9887_set_insmod(struct dvb_frontend *fe) static int tda9887_do_config(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; char *buf = priv->data; if (priv->config & TDA9887_PORT1_ACTIVE) @@ -526,12 +525,12 @@ static int tda9887_do_config(struct dvb_frontend *fe) buf[2] |= (priv->config >> 8) & cTopMask; } if ((priv->config & TDA9887_INTERCARRIER_NTSC) && - (t->std & V4L2_STD_NTSC)) + (priv->std & V4L2_STD_NTSC)) buf[1] &= ~cQSS; if (priv->config & TDA9887_GATING_18) buf[3] &= ~cGating_36; - if (t->mode == V4L2_TUNER_RADIO) { + if (priv->mode == V4L2_TUNER_RADIO) { if (priv->config & TDA9887_RIF_41_3) { buf[3] &= ~cVideoIFMask; buf[3] |= cRadioIF_41_30; @@ -561,7 +560,6 @@ static int tda9887_status(struct dvb_frontend *fe) static void tda9887_configure(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; int rc; memset(priv->data,0,sizeof(priv->data)); @@ -586,9 +584,8 @@ static void tda9887_configure(struct dvb_frontend *fe) tda9887_do_config(fe); tda9887_set_insmod(fe); - if (t->mode == T_STANDBY) { + if (priv->mode == T_STANDBY) priv->data[1] |= cForcedMuteAudioON; - } tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1],priv->data[2],priv->data[3]); @@ -633,12 +630,21 @@ static int tda9887_get_afc(struct dvb_frontend *fe) static void tda9887_standby(struct dvb_frontend *fe) { + struct tda9887_priv *priv = fe->analog_demod_priv; + + priv->mode = T_STANDBY; + tda9887_configure(fe); } static void tda9887_set_params(struct dvb_frontend *fe, struct analog_parameters *params) { + struct tda9887_priv *priv = fe->analog_demod_priv; + + priv->mode = params->mode; + priv->audmode = params->audmode; + priv->std = params->std; tda9887_configure(fe); } @@ -681,7 +687,6 @@ int tda9887_attach(struct tuner *t) priv->i2c_props.addr = t->i2c->addr; priv->i2c_props.adap = t->i2c->adapter; - priv->t = t; strlcpy(t->i2c->name, "tda9887", sizeof(t->i2c->name)); -- cgit v1.2.3 From 29f28adf65d38e079fc3f90a62920be6f9b27d0b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Dec 2007 18:11:46 -0500 Subject: tda9887: remove dependency on struct tuner From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/video/tda9887.c | 22 +++++++++++----------- linux/drivers/media/video/tda9887.h | 13 +++++++++---- linux/drivers/media/video/tuner-core.c | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 039afe418..2eb554d06 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -13,6 +13,7 @@ #endif #include #include +#include "tuner-driver.h" #include "tuner-i2c.h" #include "tda9887.h" @@ -676,26 +677,25 @@ static struct analog_tuner_ops tda9887_tuner_ops = { .set_config = tda9887_set_config, }; -int tda9887_attach(struct tuner *t) +struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, + u8 i2c_addr) { struct tda9887_priv *priv = NULL; priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); if (priv == NULL) - return -ENOMEM; - t->fe.analog_demod_priv = priv; + return NULL; + fe->analog_demod_priv = priv; - priv->i2c_props.addr = t->i2c->addr; - priv->i2c_props.adap = t->i2c->adapter; + priv->i2c_props.addr = i2c_addr; + priv->i2c_props.adap = i2c_adap; - strlcpy(t->i2c->name, "tda9887", sizeof(t->i2c->name)); + tda9887_info("tda988[5/6/7] found\n"); - tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c->addr, - t->i2c->driver->driver.name); + fe->ops.analog_demod_ops = &tda9887_tuner_ops; - t->fe.ops.analog_demod_ops = &tda9887_tuner_ops; - - return 0; + return fe; } EXPORT_SYMBOL_GPL(tda9887_attach); diff --git a/linux/drivers/media/video/tda9887.h b/linux/drivers/media/video/tda9887.h index b879f0ec2..8f873a8e6 100644 --- a/linux/drivers/media/video/tda9887.h +++ b/linux/drivers/media/video/tda9887.h @@ -17,16 +17,21 @@ #ifndef __TDA9887_H__ #define __TDA9887_H__ -#include "tuner-driver.h" +#include +#include "dvb_frontend.h" /* ------------------------------------------------------------------------ */ #if defined(CONFIG_TUNER_TDA9887) || (defined(CONFIG_TUNER_TDA9887_MODULE) && defined(MODULE)) -extern int tda9887_attach(struct tuner *t); +extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, + u8 i2c_addr); #else -static inline int tda9887_attach(struct tuner *t) +static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, + u8 i2c_addr) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); - return -EINVAL; + return NULL; } #endif diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 5b5a38eaf..45b955c3c 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -437,7 +437,7 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } case TUNER_TDA9887: - tda9887_attach(t); + tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr); break; default: attach_simple_tuner(t); -- cgit v1.2.3 From f2cffffe592e4b1dc2cfbf0f4be509edea199d5a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Dec 2007 19:20:21 -0500 Subject: tda9887: use printk macros from tuner-i2c.h From: Michael Krufky replace tda9887_info and tda9887_dbg printk macros with tuner_info and tuner_dbg, defined in tuner-i2c.h Signed-off-by: Michael Krufky --- linux/drivers/media/video/tda9887.c | 145 +++++++++++++++++------------------- 1 file changed, 70 insertions(+), 75 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index 2eb554d06..fa328768f 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -26,18 +26,11 @@ Used as part of several tuners */ -static int tda9887_debug; -module_param_named(debug, tda9887_debug, int, 0644); - -#define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "tda9887 %d-%04x: " fmt, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr, ##arg); } while (0) -#define tda9887_dbg(fmt, arg...) do {\ - if (tda9887_debug) \ - printk(KERN_INFO "tda9887 %d-%04x: " fmt, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr, ##arg); } while (0) +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable verbose debug messages"); + +#define PREFIX "tda9887" struct tda9887_priv { struct tuner_i2c_props i2c_props; @@ -299,12 +292,12 @@ static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf) "+ 37.5 kHz", "+ 12.5 kHz", }; - tda9887_info("read: 0x%2x\n", buf[0]); - tda9887_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); - tda9887_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); - tda9887_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low"); - tda9887_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); - tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); + tuner_info("read: 0x%2x\n", buf[0]); + tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); + tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); + tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low"); + tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); + tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); } static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) @@ -349,58 +342,60 @@ static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) "44 MHz", }; - tda9887_info("write: byte B 0x%02x\n",buf[1]); - tda9887_info(" B0 video mode : %s\n", - (buf[1] & 0x01) ? "video trap" : "sound trap"); - tda9887_info(" B1 auto mute fm : %s\n", - (buf[1] & 0x02) ? "yes" : "no"); - tda9887_info(" B2 carrier mode : %s\n", - (buf[1] & 0x04) ? "QSS" : "Intercarrier"); - tda9887_info(" B3-4 tv sound/radio : %s\n", - sound[(buf[1] & 0x18) >> 3]); - tda9887_info(" B5 force mute audio: %s\n", - (buf[1] & 0x20) ? "yes" : "no"); - tda9887_info(" B6 output port 1 : %s\n", - (buf[1] & 0x40) ? "high (inactive)" : "low (active)"); - tda9887_info(" B7 output port 2 : %s\n", - (buf[1] & 0x80) ? "high (inactive)" : "low (active)"); - - tda9887_info("write: byte C 0x%02x\n",buf[2]); - tda9887_info(" C0-4 top adjustment : %s dB\n", adjust[buf[2] & 0x1f]); - tda9887_info(" C5-6 de-emphasis : %s\n", deemph[(buf[2] & 0x60) >> 5]); - tda9887_info(" C7 audio gain : %s\n", - (buf[2] & 0x80) ? "-6" : "0"); - - tda9887_info("write: byte E 0x%02x\n",buf[3]); - tda9887_info(" E0-1 sound carrier : %s\n", - carrier[(buf[3] & 0x03)]); - tda9887_info(" E6 l pll gating : %s\n", - (buf[3] & 0x40) ? "36" : "13"); + tuner_info("write: byte B 0x%02x\n", buf[1]); + tuner_info(" B0 video mode : %s\n", + (buf[1] & 0x01) ? "video trap" : "sound trap"); + tuner_info(" B1 auto mute fm : %s\n", + (buf[1] & 0x02) ? "yes" : "no"); + tuner_info(" B2 carrier mode : %s\n", + (buf[1] & 0x04) ? "QSS" : "Intercarrier"); + tuner_info(" B3-4 tv sound/radio : %s\n", + sound[(buf[1] & 0x18) >> 3]); + tuner_info(" B5 force mute audio: %s\n", + (buf[1] & 0x20) ? "yes" : "no"); + tuner_info(" B6 output port 1 : %s\n", + (buf[1] & 0x40) ? "high (inactive)" : "low (active)"); + tuner_info(" B7 output port 2 : %s\n", + (buf[1] & 0x80) ? "high (inactive)" : "low (active)"); + + tuner_info("write: byte C 0x%02x\n", buf[2]); + tuner_info(" C0-4 top adjustment : %s dB\n", + adjust[buf[2] & 0x1f]); + tuner_info(" C5-6 de-emphasis : %s\n", + deemph[(buf[2] & 0x60) >> 5]); + tuner_info(" C7 audio gain : %s\n", + (buf[2] & 0x80) ? "-6" : "0"); + + tuner_info("write: byte E 0x%02x\n", buf[3]); + tuner_info(" E0-1 sound carrier : %s\n", + carrier[(buf[3] & 0x03)]); + tuner_info(" E6 l pll gating : %s\n", + (buf[3] & 0x40) ? "36" : "13"); if (buf[1] & 0x08) { /* radio */ - tda9887_info(" E2-4 video if : %s\n", - rif[(buf[3] & 0x0c) >> 2]); - tda9887_info(" E7 vif agc output : %s\n", - (buf[3] & 0x80) - ? ((buf[3] & 0x10) ? "fm-agc radio" : "sif-agc radio") - : "fm radio carrier afc"); + tuner_info(" E2-4 video if : %s\n", + rif[(buf[3] & 0x0c) >> 2]); + tuner_info(" E7 vif agc output : %s\n", + (buf[3] & 0x80) + ? ((buf[3] & 0x10) ? "fm-agc radio" : + "sif-agc radio") + : "fm radio carrier afc"); } else { /* video */ - tda9887_info(" E2-4 video if : %s\n", - vif[(buf[3] & 0x1c) >> 2]); - tda9887_info(" E5 tuner gain : %s\n", - (buf[3] & 0x80) - ? ((buf[3] & 0x20) ? "external" : "normal") - : ((buf[3] & 0x20) ? "minimum" : "normal")); - tda9887_info(" E7 vif agc output : %s\n", - (buf[3] & 0x80) - ? ((buf[3] & 0x20) - ? "pin3 port, pin22 vif agc out" - : "pin22 port, pin3 vif acg ext in") - : "pin3+pin22 port"); + tuner_info(" E2-4 video if : %s\n", + vif[(buf[3] & 0x1c) >> 2]); + tuner_info(" E5 tuner gain : %s\n", + (buf[3] & 0x80) + ? ((buf[3] & 0x20) ? "external" : "normal") + : ((buf[3] & 0x20) ? "minimum" : "normal")); + tuner_info(" E7 vif agc output : %s\n", + (buf[3] & 0x80) ? ((buf[3] & 0x20) + ? "pin3 port, pin22 vif agc out" + : "pin22 port, pin3 vif acg ext in") + : "pin3+pin22 port"); } - tda9887_info("--\n"); + tuner_info("--\n"); } /* ---------------------------------------------------------------------- */ @@ -426,11 +421,11 @@ static int tda9887_set_tvnorm(struct dvb_frontend *fe) } } if (NULL == norm) { - tda9887_dbg("Unsupported tvnorm entry - audio muted\n"); + tuner_dbg("Unsupported tvnorm entry - audio muted\n"); return -1; } - tda9887_dbg("configure for: %s\n",norm->name); + tuner_dbg("configure for: %s\n", norm->name); buf[1] = norm->b; buf[2] = norm->c; buf[3] = norm->e; @@ -553,7 +548,7 @@ static int tda9887_status(struct dvb_frontend *fe) memset(buf,0,sizeof(buf)); if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1))) - tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); + tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc); dump_read_message(fe, buf); return 0; } @@ -588,15 +583,15 @@ static void tda9887_configure(struct dvb_frontend *fe) if (priv->mode == T_STANDBY) priv->data[1] |= cForcedMuteAudioON; - tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", - priv->data[1],priv->data[2],priv->data[3]); - if (tda9887_debug > 1) + tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", + priv->data[1], priv->data[2], priv->data[3]); + if (debug > 1) dump_write_message(fe, priv->data); if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4))) - tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); + tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc); - if (tda9887_debug > 2) { + if (debug > 2) { msleep_interruptible(1000); tda9887_status(fe); } @@ -607,8 +602,8 @@ static void tda9887_configure(struct dvb_frontend *fe) static void tda9887_tuner_status(struct dvb_frontend *fe) { struct tda9887_priv *priv = fe->analog_demod_priv; - tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", - priv->data[1], priv->data[2], priv->data[3]); + tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", + priv->data[1], priv->data[2], priv->data[3]); } static int tda9887_get_afc(struct dvb_frontend *fe) @@ -691,7 +686,7 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; - tda9887_info("tda988[5/6/7] found\n"); + tuner_info("tda988[5/6/7] found\n"); fe->ops.analog_demod_ops = &tda9887_tuner_ops; -- cgit v1.2.3 From 792fe12a080524a1a417780cc115efe7384a3223 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Dec 2007 20:02:26 -0500 Subject: tuner: remove struct tuner from tuner-driver.h From: Michael Krufky struct tuner holds state for tuner-core, only -- move it into tuner-core.c Signed-off-by: Michael Krufky --- linux/drivers/media/video/tuner-core.c | 21 +++++++++++++++++++++ linux/drivers/media/video/tuner-driver.h | 23 ----------------------- 2 files changed, 21 insertions(+), 23 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 45b955c3c..73976746b 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -41,6 +41,27 @@ #define PREFIX t->i2c->driver->driver.name #endif +struct tuner { + /* device */ + struct dvb_frontend fe; + struct i2c_client *i2c; + struct list_head list; + unsigned int using_v4l2:1; + + /* keep track of the current settings */ + v4l2_std_id std; + unsigned int tv_freq; + unsigned int radio_freq; + unsigned int audmode; + + unsigned int mode; + unsigned int mode_mask; /* Combination of allowable modes */ + + unsigned int type; /* chip type id */ + unsigned int config; + int (*tuner_callback) (void *dev, int command, int arg); +}; + /* standard i2c insmod options */ static unsigned short normal_i2c[] = { #if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE)) diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 417753b7c..7b1adfaf7 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -50,27 +50,4 @@ struct analog_tuner_ops { int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); }; -struct tuner { - /* device */ - struct i2c_client *i2c; - struct list_head list; /* list of tuners */ - - unsigned int type; /* chip type */ - - unsigned int mode; - unsigned int mode_mask; /* Combination of allowable modes */ - - unsigned int tv_freq; /* keep track of the current settings */ - unsigned int radio_freq; - unsigned int audmode; - v4l2_std_id std; - - int using_v4l2; - - struct dvb_frontend fe; - - unsigned int config; - int (*tuner_callback) (void *dev, int command,int arg); -}; - #endif /* __TUNER_DRIVER_H__ */ -- cgit v1.2.3 From a5484362451f73f18dafd3dbcf9fedac5ed07ee4 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Dec 2007 23:21:08 -0500 Subject: tuner: remove unneeded #includes from tuner-driver.h From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/video/tuner-driver.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-driver.h b/linux/drivers/media/video/tuner-driver.h index 7b1adfaf7..5eaa30ccb 100644 --- a/linux/drivers/media/video/tuner-driver.h +++ b/linux/drivers/media/video/tuner-driver.h @@ -22,8 +22,6 @@ #ifndef __TUNER_DRIVER_H__ #define __TUNER_DRIVER_H__ -#include -#include #include "dvb_frontend.h" extern unsigned const int tuner_count; -- cgit v1.2.3 From a45db7876a01ca11ac6b66b14f274a4916856306 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 17 Dec 2007 07:49:33 -0500 Subject: tda9887: initialize mode to T_STANDBY at startup From: Michael Krufky Ensure that the audio is muted at attach-time Signed-off-by: Michael Krufky --- linux/drivers/media/video/tda9887.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c index fa328768f..8377facca 100644 --- a/linux/drivers/media/video/tda9887.c +++ b/linux/drivers/media/video/tda9887.c @@ -685,6 +685,7 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->mode = T_STANDBY; tuner_info("tda988[5/6/7] found\n"); -- cgit v1.2.3 From 9b9f1ee84c2c20af88227ddde46fcc3114692c89 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Dec 2007 11:35:59 -0200 Subject: Fix CodingStyle troubles caused by the previous cx88 commits From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-blackbird.c | 10 ++++------ linux/drivers/media/video/cx88/cx88-video.c | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index d16a3cd72..c250297db 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -604,13 +604,11 @@ static int blackbird_start_codec(struct file *file, void *priv) int lastchange = -1; int lastval = 0; - for (i=0; (i < 10) && (i < (lastchange + 4)); i++) - { + for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) { reg = cx_read(AUD_STATUS); - dprintk(1,"AUD_STATUS:%dL: 0x%x\n", i, reg); - if ((reg & 0x0F) != lastval) - { + dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg); + if ((reg & 0x0F) != lastval) { lastval = reg & 0x0F; lastchange = i; } @@ -620,7 +618,7 @@ static int blackbird_start_codec(struct file *file, void *priv) /* unmute audio source */ cx_clear(AUD_VOL_CTL, (1 << 6)); - blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0); + blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0); /* initialize the video input */ blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index fe6c66a58..ef795d353 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -437,7 +437,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) route.input = INPUT(input).audioroute; cx88_call_i2c_clients(core, - VIDIOC_INT_S_AUDIO_ROUTING,&route); + VIDIOC_INT_S_AUDIO_ROUTING, &route); } -- cgit v1.2.3 From fd0eb1330fbf94092ddce4459864e00f9ffded65 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Dec 2007 11:54:06 -0200 Subject: Convert cx88_input.audioroute to a bitfield From: Michael Krufky Prevent us from wasting some extra bytes of memory Thanks to Trent Piepho, for pointing this out. Cc: Trent Piepho Cc: Ricardo Cerqueira Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index b193a26ce..0f32cbfbb 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -231,7 +231,7 @@ struct cx88_input { enum cx88_itype type; u32 gpio0, gpio1, gpio2, gpio3; unsigned int vmux:2; - unsigned int audioroute; + unsigned int audioroute:2; }; struct cx88_board { -- cgit v1.2.3 From bb76d5869181e4c5eb84019976eed7c2c6fc0171 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Dec 2007 15:26:29 -0200 Subject: bttv: check pci_register_driver() error From: Akinobu Mita Check pci_register_driver() error in module_init. Signed-off-by: Akinobu Mita Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-driver.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 3efc9465b..494afcbe6 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -4481,7 +4481,11 @@ static int __init bttv_init_module(void) return ret; } #endif - return pci_register_driver(&bttv_pci_driver); + ret = pci_register_driver(&bttv_pci_driver); + if (ret < 0) + bus_unregister(&bttv_sub_bus_type); + + return ret; } static void __exit bttv_cleanup_module(void) @@ -4490,7 +4494,6 @@ static void __exit bttv_cleanup_module(void) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) bus_unregister(&bttv_sub_bus_type); #endif - return; } module_init(bttv_init_module); -- cgit v1.2.3 From e0b7504caf309e3f34c1fecdfc0c570c60c6d648 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Dec 2007 14:49:17 -0200 Subject: V4L/DVB (em28xx): Add support for Pinnacle Dazzle DVC 100 From: Aurelien Jarno The patch below adds the "Pinnacle Dazzle DVC 100" to the list of cards supported by the em28xx driver. As the configuration is the same as the DVC 90 one, it simply adds a new USB ID to the list of devices supported by the DVC 90 configuration. Signed-off-by: Aurelien Jarno Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.em28xx | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index ceb277543..dbc19ca9e 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -7,7 +7,7 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) 8 -> Kworld USB2800 (em2800) - 9 -> Pinnacle Dazzle DVC 90 (em2820/em2840) [2304:0207] + 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 7bca01008..809cc0a4a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -330,7 +330,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90", + .name = "Pinnacle Dazzle DVC 90/DVC 100", .vchannels = 3, .has_tuner = 0, .decoder = EM28XX_SAA7113, @@ -417,6 +417,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, + { USB_DEVICE(0x2304, 0x021a), + .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x2040, 0x6513), -- cgit v1.2.3 From 462190e49962234691889a05d155f804f4c10c71 Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Sun, 2 Dec 2007 19:30:50 +1000 Subject: xc2028: include int_freq in firmware version display From: Chris Pascoe Add "int_freq" to the debugging output when selecting firmware and the HAS_IF flag when dumping firmware during load. Signed-off-by: Chris Pascoe --- linux/drivers/media/video/tuner-xc2028.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 29c5faf62..b2e471ee7 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -159,7 +159,8 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) return 0; } -void dump_firm_type(unsigned int type) +#define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) +void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) { if (type & BASE) printk("BASE "); @@ -221,6 +222,8 @@ void dump_firm_type(unsigned int type) printk("INPUT2 "); if (type & SCODE) printk("SCODE "); + if (type & HAS_IF) + printk("HAS_IF_%d ", int_freq); } static v4l2_std_id parse_audio_std_option(void) @@ -365,9 +368,9 @@ static int load_all_firmwares(struct dvb_frontend *fe) } tuner_dbg("Reading firmware type "); if (debug) { - dump_firm_type(type); + dump_firm_type_and_int_freq(type, int_freq); printk("(%x), id %llx, size=%d.\n", - type, (unsigned long long)id, size); + type, (unsigned long long)id, size); } memcpy(priv->firm[n].ptr, p, size); @@ -627,7 +630,8 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, } tuner_info("Loading SCODE for type="); - dump_firm_type(priv->firm[pos].type); + dump_firm_type_and_int_freq(priv->firm[pos].type, + priv->firm[pos].int_freq); printk("(%x), id %016llx.\n", priv->firm[pos].type, (unsigned long long)*id); @@ -685,11 +689,15 @@ retry: tuner_dbg("checking firmware, user requested type="); if (debug) { dump_firm_type(new_fw.type); - printk("(%x), id %016llx, scode_tbl ", new_fw.type, + printk("(%x), id %016llx, ", new_fw.type, (unsigned long long)new_fw.std_req); - dump_firm_type(priv->ctrl.scode_table); - printk("(%x), scode_nr %d\n", priv->ctrl.scode_table, - new_fw.scode_nr); + if (!int_freq) { + printk("scode_tbl "); + dump_firm_type(priv->ctrl.scode_table); + printk("(%x), ", priv->ctrl.scode_table); + } else + printk("int_freq %d, ", new_fw.int_freq); + printk("scode_nr %d\n", new_fw.scode_nr); } /* No need to reload base firmware if it matches */ -- cgit v1.2.3 From eaa733af398f50375e2de38be27d489a16fd1739 Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Sun, 2 Dec 2007 19:36:42 +1000 Subject: xc2028: s-code offset should not modify internal control structure From: Chris Pascoe Don't modify the control structure that was provided at attach when applying an offset to the S-Code, otherwise it will be incorrect on subsequent tunes. Signed-off-by: Chris Pascoe --- linux/drivers/media/video/tuner-xc2028.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index b2e471ee7..cf5d1f7e6 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -971,6 +971,7 @@ static int xc2028_set_params(struct dvb_frontend *fe, struct xc2028_data *priv = fe->tuner_priv; unsigned int type=0; fe_bandwidth_t bw = BANDWIDTH_8_MHZ; + u16 demod = 0; tuner_dbg("%s called\n", __FUNCTION__); @@ -1024,10 +1025,10 @@ static int xc2028_set_params(struct dvb_frontend *fe, /* All S-code tables need a 200kHz shift */ if (priv->ctrl.demod) - priv->ctrl.demod += 200; + demod = priv->ctrl.demod + 200; return generic_set_freq(fe, p->frequency, - T_DIGITAL_TV, type, 0, priv->ctrl.demod); + T_DIGITAL_TV, type, 0, demod); } static int xc2028_sleep(struct dvb_frontend *fe) -- cgit v1.2.3 From ae76e3fe59fcc553239b3a9a8f0514014b9b44ee Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Sun, 2 Dec 2007 19:54:17 +1000 Subject: xc2028: check HAS_IF flag against table From: Chris Pascoe When searching for the right S-Code table to load, check the HAS_IF flag against the firmware we are checking instead of against the the "type" requested. We already ignore the scode type requested if the caller passed an int_freq; this makes the search by frequency consistent with that behaviour. Signed-off-by: Chris Pascoe --- linux/drivers/media/video/tuner-xc2028.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index cf5d1f7e6..819cf2e5d 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -607,7 +607,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, } else { for (pos = 0; pos < priv->firm_size; pos++) { if ((priv->firm[pos].int_freq == int_freq) && - (type & HAS_IF)) + (priv->firm[pos].type & HAS_IF)) break; } if (pos == priv->firm_size) @@ -616,7 +616,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, p = priv->firm[pos].ptr; - if (type & HAS_IF) { + if (priv->firm[pos].type & HAS_IF) { if (priv->firm[pos].size != 12 * 16 || scode >= 16) return -EINVAL; p += 12 * scode; -- cgit v1.2.3 From 00ab6c90dc98d2413de98eebf8638f1f38a365af Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Sun, 2 Dec 2007 22:39:18 +1000 Subject: xc2028: be more specific about when applying offset for 7MHz channels From: Chris Pascoe We have been inserting a mystery 500kHz offset for tuning 7MHz channels, however some experimentation reveals it is only needed under certain conditions with specific firmware combinations. Document these and only apply the offset when we know it is required. Signed-off-by: Chris Pascoe --- linux/drivers/media/video/tuner-xc2028.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 819cf2e5d..71756cabf 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -890,7 +890,16 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, rc = send_seq(priv, {0x00, 0x00}); } else { offset = 2750000; - if (priv->cur_fw.type & DTV7) + /* + * We must adjust the offset by 500kHz in two cases in order + * to correctly center the IF output: + * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly + * selected and a 7MHz channel is tuned; + * 2) When tuning a VHF channel with DTV78 firmware. + */ + if (((priv->cur_fw.type & DTV7) && + (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) || + ((priv->cur_fw.type & DTV78) && freq < 470000000)) offset -= 500000; } -- cgit v1.2.3 From d0188f79d5ca5c89b9106c3a99f9eefe465b5f5e Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Sun, 2 Dec 2007 23:07:06 +1000 Subject: xc2028: select DTV78 firmware if tuning 7MHz VHF / 8MHz UHF From: Chris Pascoe It seems that the DTV78 firmware is intended for use in locations where VHF channels have 7MHz bandwidth and UHF channels have 8MHz bandwidth. If we switch to DTV78 firmware when we detect this condition, we can avoid firmware reloads when switching between VHF and UHF transponders. Place the state for this in the control structure so that card drivers can hint to us to use DTV78 firmware from the first tuning attempt. Signed-off-by: Chris Pascoe --- linux/drivers/media/video/tuner-xc2028.c | 23 +++++++++++++++-------- linux/drivers/media/video/tuner-xc2028.h | 2 ++ 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 71756cabf..0dbb648ae 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -1013,20 +1013,27 @@ static int xc2028_set_params(struct dvb_frontend *fe, return -EINVAL; } - /* FIXME: - There are two Scodes that will never be selected: - DTV78 ZARLINK456, DTV78 DIBCOM52 - When it should opt for DTV78 instead of DTV7 or DTV8? - */ switch (bw) { case BANDWIDTH_8_MHZ: - type |= DTV8 | F8MHZ; + if (p->frequency < 470000000) + priv->ctrl.vhfbw7 = 0; + else + priv->ctrl.uhfbw8 = 1; + type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8; + type |= F8MHZ; break; case BANDWIDTH_7_MHZ: - type |= DTV7 | F8MHZ; + if (p->frequency < 470000000) + priv->ctrl.vhfbw7 = 1; + else + priv->ctrl.uhfbw8 = 0; + type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7; + type |= F8MHZ; break; case BANDWIDTH_6_MHZ: - type |= DTV6 ; + type |= DTV6; + priv->ctrl.vhfbw7 = 0; + priv->ctrl.uhfbw8 = 0; break; default: tuner_err("error: bandwidth not supported.\n"); diff --git a/linux/drivers/media/video/tuner-xc2028.h b/linux/drivers/media/video/tuner-xc2028.h index 1fe8b1959..7462629b9 100644 --- a/linux/drivers/media/video/tuner-xc2028.h +++ b/linux/drivers/media/video/tuner-xc2028.h @@ -30,6 +30,8 @@ struct xc2028_ctrl { unsigned int mts :1; unsigned int d2633 :1; unsigned int input1:1; + unsigned int vhfbw7:1; + unsigned int uhfbw8:1; unsigned int demod; }; -- cgit v1.2.3 From 4aa850a10cbb11ef537e296dedcc0431f1431d60 Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Sat, 15 Dec 2007 16:24:00 +1000 Subject: zl10353: improve tuning parameters and update register map From: Chris Pascoe Some more I2C traces and a experimentation with register values on both the ZL10353 and MT352 mean that I can now guess at what more of the ZL10353 registers do. Guess at the registers' names (based on the equivalent names in MT352) and update set_parameters/get_parameters with the new knowledge. Signed-off-by: Chris Pascoe --- linux/drivers/media/dvb/frontends/zl10353.c | 243 +++++++++++++++++++++-- linux/drivers/media/dvb/frontends/zl10353_priv.h | 15 ++ 2 files changed, 245 insertions(+), 13 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index bc8e7b0f5..79802e023 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -37,6 +37,8 @@ struct zl10353_state { struct dvb_frontend frontend; struct zl10353_config config; + + enum fe_bandwidth bandwidth; }; static int debug; @@ -200,27 +202,156 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, { struct zl10353_state *state = fe->demodulator_priv; u16 nominal_rate, input_freq; - u8 pllbuf[6] = { 0x67 }; + u8 pllbuf[6] = { 0x67 }, acq_ctl = 0; + u16 tps = 0; + struct dvb_ofdm_parameters *op = ¶m->u.ofdm; - /* These settings set "auto-everything" and start the FSM. */ - zl10353_single_write(fe, 0x55, 0x80); + zl10353_single_write(fe, RESET, 0x80); udelay(200); zl10353_single_write(fe, 0xEA, 0x01); udelay(200); zl10353_single_write(fe, 0xEA, 0x00); - zl10353_single_write(fe, 0x56, 0x28); - zl10353_single_write(fe, 0x89, 0x20); - zl10353_single_write(fe, 0x5E, 0x00); + zl10353_single_write(fe, AGC_TARGET, 0x28); + + if (op->transmission_mode != TRANSMISSION_MODE_AUTO) + acq_ctl |= (1 << 0); + if (op->guard_interval != GUARD_INTERVAL_AUTO) + acq_ctl |= (1 << 1); + zl10353_single_write(fe, ACQ_CTL, acq_ctl); - zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate); + switch (op->bandwidth) { + case BANDWIDTH_6_MHZ: + /* These are extrapolated from the 7 and 8MHz values */ + zl10353_single_write(fe, MCLK_RATIO, 0x97); + zl10353_single_write(fe, 0x64, 0x34); + break; + case BANDWIDTH_7_MHZ: + zl10353_single_write(fe, MCLK_RATIO, 0x86); + zl10353_single_write(fe, 0x64, 0x35); + break; + case BANDWIDTH_8_MHZ: + default: + zl10353_single_write(fe, MCLK_RATIO, 0x75); + zl10353_single_write(fe, 0x64, 0x36); + } + + zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate); zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate)); zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate)); + state->bandwidth = op->bandwidth; zl10353_calc_input_freq(fe, &input_freq); zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq)); zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq)); + /* Hint at TPS settings */ + switch (op->code_rate_HP) { + case FEC_2_3: + tps |= (1 << 7); + break; + case FEC_3_4: + tps |= (2 << 7); + break; + case FEC_5_6: + tps |= (3 << 7); + break; + case FEC_7_8: + tps |= (4 << 7); + break; + case FEC_1_2: + case FEC_AUTO: + break; + default: + return -EINVAL; + } + + switch (op->code_rate_LP) { + case FEC_2_3: + tps |= (1 << 4); + break; + case FEC_3_4: + tps |= (2 << 4); + break; + case FEC_5_6: + tps |= (3 << 4); + break; + case FEC_7_8: + tps |= (4 << 4); + break; + case FEC_1_2: + case FEC_AUTO: + break; + case FEC_NONE: + if (op->hierarchy_information == HIERARCHY_AUTO || + op->hierarchy_information == HIERARCHY_NONE) + break; + default: + return -EINVAL; + } + + switch (op->constellation) { + case QPSK: + break; + case QAM_AUTO: + case QAM_16: + tps |= (1 << 13); + break; + case QAM_64: + tps |= (2 << 13); + break; + default: + return -EINVAL; + } + + switch (op->transmission_mode) { + case TRANSMISSION_MODE_2K: + case TRANSMISSION_MODE_AUTO: + break; + case TRANSMISSION_MODE_8K: + tps |= (1 << 0); + break; + default: + return -EINVAL; + } + + switch (op->guard_interval) { + case GUARD_INTERVAL_1_32: + case GUARD_INTERVAL_AUTO: + break; + case GUARD_INTERVAL_1_16: + tps |= (1 << 2); + break; + case GUARD_INTERVAL_1_8: + tps |= (2 << 2); + break; + case GUARD_INTERVAL_1_4: + tps |= (3 << 2); + break; + default: + return -EINVAL; + } + + switch (op->hierarchy_information) { + case HIERARCHY_AUTO: + case HIERARCHY_NONE: + break; + case HIERARCHY_1: + tps |= (1 << 10); + break; + case HIERARCHY_2: + tps |= (2 << 10); + break; + case HIERARCHY_4: + tps |= (3 << 10); + break; + default: + return -EINVAL; + } + + zl10353_single_write(fe, TPS_GIVEN_1, msb(tps)); + zl10353_single_write(fe, TPS_GIVEN_0, lsb(tps)); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); @@ -249,12 +380,97 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, else zl10353_single_write(fe, TUNER_GO, 0x01); - udelay(250); - zl10353_single_write(fe, 0xE4, 0x00); - zl10353_single_write(fe, 0xE5, 0x2A); - zl10353_single_write(fe, 0xE9, 0x02); - zl10353_single_write(fe, 0xE7, 0x40); - zl10353_single_write(fe, 0xE8, 0x10); + return 0; +} + +static int zl10353_get_parameters(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct zl10353_state *state = fe->demodulator_priv; + struct dvb_ofdm_parameters *op = ¶m->u.ofdm; + int s6, s9; + u16 tps; + static const u8 tps_fec_to_api[8] = { + FEC_1_2, + FEC_2_3, + FEC_3_4, + FEC_5_6, + FEC_7_8, + FEC_AUTO, + FEC_AUTO, + FEC_AUTO + }; + + s6 = zl10353_read_register(state, STATUS_6); + s9 = zl10353_read_register(state, STATUS_9); + if (s6 < 0 || s9 < 0) + return -EREMOTEIO; + if ((s6 & (1 << 5)) == 0 || (s9 & (1 << 4)) == 0) + return -EINVAL; /* no FE or TPS lock */ + + tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 | + zl10353_read_register(state, TPS_RECEIVED_0); + + op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7]; + op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7]; + + switch ((tps >> 13) & 3) { + case 0: + op->constellation = QPSK; + break; + case 1: + op->constellation = QAM_16; + break; + case 2: + op->constellation = QAM_64; + break; + default: + op->constellation = QAM_AUTO; + break; + } + + op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K : + TRANSMISSION_MODE_2K; + + switch ((tps >> 2) & 3) { + case 0: + op->guard_interval = GUARD_INTERVAL_1_32; + break; + case 1: + op->guard_interval = GUARD_INTERVAL_1_16; + break; + case 2: + op->guard_interval = GUARD_INTERVAL_1_8; + break; + case 3: + op->guard_interval = GUARD_INTERVAL_1_4; + break; + default: + op->guard_interval = GUARD_INTERVAL_AUTO; + break; + } + + switch ((tps >> 10) & 7) { + case 0: + op->hierarchy_information = HIERARCHY_NONE; + break; + case 1: + op->hierarchy_information = HIERARCHY_1; + break; + case 2: + op->hierarchy_information = HIERARCHY_2; + break; + case 3: + op->hierarchy_information = HIERARCHY_4; + break; + default: + op->hierarchy_information = HIERARCHY_AUTO; + break; + } + + param->frequency = 0; + op->bandwidth = state->bandwidth; + param->inversion = INVERSION_AUTO; return 0; } @@ -449,6 +665,7 @@ static struct dvb_frontend_ops zl10353_ops = { .write = zl10353_write, .set_frontend = zl10353_set_parameters, + .get_frontend = zl10353_get_parameters, .get_tune_settings = zl10353_get_tune_settings, .read_status = zl10353_read_status, diff --git a/linux/drivers/media/dvb/frontends/zl10353_priv.h b/linux/drivers/media/dvb/frontends/zl10353_priv.h index fcad92219..055ff1f7e 100644 --- a/linux/drivers/media/dvb/frontends/zl10353_priv.h +++ b/linux/drivers/media/dvb/frontends/zl10353_priv.h @@ -46,13 +46,28 @@ enum zl10353_reg_addr { RS_ERR_CNT_0 = 0x13, RS_UBC_1 = 0x14, RS_UBC_0 = 0x15, + TPS_RECEIVED_1 = 0x1D, + TPS_RECEIVED_0 = 0x1E, + TPS_CURRENT_1 = 0x1F, + TPS_CURRENT_0 = 0x20, + RESET = 0x55, + AGC_TARGET = 0x56, + MCLK_RATIO = 0x5C, + ACQ_CTL = 0x5E, TRL_NOMINAL_RATE_1 = 0x65, TRL_NOMINAL_RATE_0 = 0x66, INPUT_FREQ_1 = 0x6C, INPUT_FREQ_0 = 0x6D, + TPS_GIVEN_1 = 0x6E, + TPS_GIVEN_0 = 0x6F, TUNER_GO = 0x70, FSM_GO = 0x71, CHIP_ID = 0x7F, + CHAN_STEP_1 = 0xE4, + CHAN_STEP_0 = 0xE5, + OFDM_LOCK_TIME = 0xE7, + FEC_LOCK_TIME = 0xE8, + ACQ_DELAY = 0xE9, }; #endif /* _ZL10353_PRIV_ */ -- cgit v1.2.3 From a21eb25fa965ec74b9d187d2bf1758570df34b6b Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Sat, 15 Dec 2007 16:31:09 +1000 Subject: cx23885: correctly join I2C writes and reads from same address From: Chris Pascoe When an I2C message specifies a write then a read from the same I2C address, we need to tell the chip to not release the bus between the message parts. Signed-off-by: Chris Pascoe --- linux/drivers/media/video/cx23885/cx23885-i2c.c | 53 ++++++++++++++++++------- 1 file changed, 39 insertions(+), 14 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index 6e9a89da6..0ac3b6793 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -38,8 +38,10 @@ static unsigned int i2c_scan = 0; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg) +#define dprintk(level, fmt, arg...) do { \ + if (i2c_debug >= level) \ + printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg); \ + } while (0) #define I2C_WAIT_DELAY 32 #define I2C_WAIT_RETRY 64 @@ -78,14 +80,18 @@ static int i2c_wait_done(struct i2c_adapter *i2c_adap) } static int i2c_sendbytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg, int last) + const struct i2c_msg *msg, int joined_rlen) { struct cx23885_i2c *bus = i2c_adap->algo_data; struct cx23885_dev *dev = bus->dev; u32 wdata, addr, ctrl; int retval, cnt; - dprintk(1, "%s(msg->len=%d, last=%d)\n", __FUNCTION__, msg->len, last); + if (joined_rlen) + dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__, + msg->len, joined_rlen); + else + dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len); /* Deal with i2c probe functions with zero payload */ if (msg->len == 0) { @@ -108,6 +114,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (msg->len > 1) ctrl |= I2C_NOSTOP | I2C_EXTEND; + else if (joined_rlen) + ctrl |= I2C_NOSTOP; cx_write(bus->reg_addr, addr); cx_write(bus->reg_wdata, wdata); @@ -131,6 +139,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (cnt < msg->len - 1) ctrl |= I2C_NOSTOP | I2C_EXTEND; + else if (joined_rlen) + ctrl |= I2C_NOSTOP; cx_write(bus->reg_addr, addr); cx_write(bus->reg_wdata, wdata); @@ -152,19 +162,22 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, eio: retval = -EIO; err: - printk(" ERR: %d\n", retval); + if (i2c_debug) + printk(" ERR: %d\n", retval); return retval; } static int i2c_readbytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg, int last) + const struct i2c_msg *msg, int joined) { struct cx23885_i2c *bus = i2c_adap->algo_data; struct cx23885_dev *dev = bus->dev; u32 ctrl, cnt; int retval; - dprintk(1, "%s(msg->len=%d, last=%d)\n", __FUNCTION__, msg->len, last); + + if (i2c_debug && !joined) + dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len); /* Deal with i2c probe functions with zero payload */ if (msg->len == 0) { @@ -180,8 +193,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, return 0; } - if (i2c_debug) - printk(" addr << 1) + 1); + if (i2c_debug) { + if (joined) + printk(" R"); + else + printk(" addr << 1) + 1); + } for(cnt = 0; cnt < msg->len; cnt++) { @@ -210,7 +227,8 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, eio: retval = -EIO; err: - printk(" ERR: %d\n", retval); + if (i2c_debug) + printk(" ERR: %d\n", retval); return retval; } @@ -228,15 +246,22 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, __FUNCTION__, num, msgs[i].addr, msgs[i].len); if (msgs[i].flags & I2C_M_RD) { /* read */ - retval = i2c_readbytes(i2c_adap, &msgs[i], i+1 == num); + retval = i2c_readbytes(i2c_adap, &msgs[i], 0); + } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && + msgs[i].addr == msgs[i + 1].addr) { + /* write then read from same address */ + retval = i2c_sendbytes(i2c_adap, &msgs[i], + msgs[i + 1].len); if (retval < 0) goto err; + i++; + retval = i2c_readbytes(i2c_adap, &msgs[i], 1); } else { /* write */ - retval = i2c_sendbytes(i2c_adap, &msgs[i], i+1 == num); - if (retval < 0) - goto err; + retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); } + if (retval < 0) + goto err; } return num; -- cgit v1.2.3 From 3842afc175a16c86d1f3b719f07a3bfddf3c7815 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Dec 2007 01:30:52 -0200 Subject: Fix offset for ATSC From: Mauro Carvalho Chehab ATSC works with offset=0 Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-xc2028.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index 0dbb648ae..133ab1cfe 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -888,7 +888,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, */ if (new_mode == T_ANALOG_TV) { rc = send_seq(priv, {0x00, 0x00}); - } else { + } else if (!(priv->cur_fw.type & ATSC)) { offset = 2750000; /* * We must adjust the offset by 500kHz in two cases in order -- cgit v1.2.3