From patchwork Tue May 31 07:53:35 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitri Belimov X-Patchwork-Id: 6784 Return-path: Envelope-to: mchehab@pedra Delivery-date: Tue, 31 May 2011 08:31:29 -0300 Received: from mchehab by pedra with local (Exim 4.72) (envelope-from ) id 1QRNAW-0001Ec-RP for mchehab@pedra; Tue, 31 May 2011 08:31:29 -0300 Received: from casper.infradead.org [85.118.1.10] by pedra with IMAP (fetchmail-6.3.17) for (single-drop); Tue, 31 May 2011 08:31:28 -0300 (BRT) Received: from vger.kernel.org ([209.132.180.67]) by casper.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QRImO-0000K9-WD; Tue, 31 May 2011 06:50:18 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757170Ab1EaGt7 (ORCPT + 1 other); Tue, 31 May 2011 02:49:59 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:58960 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751368Ab1EaGt5 (ORCPT ); Tue, 31 May 2011 02:49:57 -0400 Received: by bwz15 with SMTP id 15so3372230bwz.19 for ; Mon, 30 May 2011 23:49:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:date:from:to:subject:message-id:x-mailer :mime-version:content-type; bh=hRmaDAH7QG/XaT0dStKkCsg7GdaNGUw3JqupHeKRkDM=; b=qJ2p+uXCebNlakLCgSEPgD8XfkqvAnGmIei2EvJUmy2kFa2XG6C+9ghLNJMvXM1e4R FUzmV5mx1QuyNXlTTySfwTfIrJ50JBkk9D7Ib+KUWCjZN622vbRP/bS0SjIPUWKqf+/7 AXGPPwLKKGQScIKWPD8XY5dXPxLzkNuGIFsIM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:subject:message-id:x-mailer:mime-version:content-type; b=npc/fwqvrX0rkU9t3rP9cIIN+CCdQMAogIDm7SjKlZ1y6FPZ+3eJkJEAoW49GFXPnA cDNyTNqL3nnfyTdFsPGCQKxSvvDua9kjTPB9iLBLGIAkSX5Jpr+smDbM5jqIXBYw70Yd vL4NcZylKeFTl/DBYqxxQUVOXik5V3wNq+OG0= Received: by 10.204.35.18 with SMTP id n18mr5171557bkd.91.1306824595561; Mon, 30 May 2011 23:49:55 -0700 (PDT) Received: from glory.local ([83.234.160.236]) by mx.google.com with ESMTPS id x13sm3953548bkj.17.2011.05.30.23.49.51 (version=SSLv3 cipher=OTHER); Mon, 30 May 2011 23:49:53 -0700 (PDT) Date: Tue, 31 May 2011 17:53:35 +1000 From: Dmitri Belimov To: Linux Media Mailing List , Mauro Carvalho Chehab Subject: [RFC] saa7134 + upd61151 Message-ID: <20110531175335.75b0ffaa@glory.local> X-Mailer: Claws Mail 3.7.6 (GTK+ 2.20.1; i486-pc-linux-gnu) Mime-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Sender: Hi This is my test patch for saa7134 and MPEG2 encoder uPD61151. My main problem is that saa7134 can has only one MPEG device attached. Our tv card has DVB-T and MPEG2 encoder. And function mops_ops_attach discard second MPEG device. I try add same as MPEG device into saa7134 driver, but it's not work. Who can help me?? [ 212.641035] Linux video capture interface: v2.00 [ 212.779837] IR NEC protocol handler initialized [ 212.801895] IR RC5(x) protocol handler initialized [ 212.835655] IR RC6 protocol handler initialized [ 212.862084] saa7130/34: v4l2 driver version 0.2.16 loaded [ 212.862123] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19 [ 212.862129] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000 [ 212.862135] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected] [ 212.862150] saa7133[0]: board init: gpio is 200000 [ 212.862156] buffer_setup set psize = 188 [ 212.875380] IR JVC protocol handler initialized [ 212.877367] IR Sony protocol handler initialized [ 212.880196] lirc_dev: IR Remote Control driver registered, major 252 [ 212.881252] IR LIRC bridge handler initialized [ 213.001012] saa7133[0]: i2c eeprom 00: ce 5a 95 75 54 20 00 00 00 00 00 00 00 00 00 01 [ 213.001031] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001049] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001067] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001084] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001101] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001119] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001136] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001154] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001171] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001188] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001208] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001216] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001224] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001232] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff [ 213.001241] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff [ 213.014427] i2c-core: driver [tuner] using legacy suspend method [ 213.014430] i2c-core: driver [tuner] using legacy resume method [ 213.017060] tuner 7-0061: Tuner -1 found with type(s) Radio TV. [ 213.017185] xc5000 7-0061: creating new instance [ 213.020020] xc5000: Successfully identified at address 0x61 [ 213.020024] xc5000: Firmware has not been loaded previously [ 213.020035] sap [ 214.827686] xc5000: I2C write failed (len=4) [ 214.827689] xc5000: xc_SetTVStandard failed [ 214.827698] sap [ 221.354013] Registered IR keymap rc-behold [ 221.354156] input: i2c IR (BeholdTV) as /devices/virtual/rc/rc0/input5 [ 221.354219] rc0: i2c IR (BeholdTV) as /devices/virtual/rc/rc0 [ 221.354223] ir-kbd-i2c: i2c IR (BeholdTV) detected at i2c-7/7-002d/ir0 [saa7133[0]] [ 221.354702] saa7134 0000:04:01.0: registered master spi32766 (dynamic) [ 221.354705] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1 [ 221.354707] saa7133[0]: found muPD61151 MPEG encoder [ 221.375343] spi spi32766.0: spi_bitbang_setup, 20 nsec/bit [ 221.375350] spi spi32766.0: setup mode 0, 8 bits/w, 50000000 Hz max --> 0 [ 221.375380] upd61151_probe function [ 221.375665] upd61151: MPEG2 core status 0 [ 221.375666] upd61151: need reload firmware [ 221.375668] Start load firmware... [ 221.375669] DEBUG: upd61151_download_firmware [ 221.378088] DEBUG: upd61151_load_base_firmware [ 221.378091] upd61151: waiting for base firmware upload (D61151_PS_7133_v22_031031.bin)... [ 221.440224] upd61151: firmware read 97002 bytes. [ 221.440226] upd61151: base firmware uploading... [ 221.440434] upd61151: Transfer IRQ status 0x0 [ 221.442098] fw upload start [ 239.219204] fw upload stop [ 239.219391] upd61151: Transfer IRQ status 0x1 [ 239.219760] upd61151: base firmware upload complete... [ 239.219954] DEBUG: upd61151_load_audio_firmware [ 239.219955] upd61151: waiting for audio firmware upload (audrey_MPE_V1r51.bin)... [ 239.248638] upd61151: firmware read 40064 bytes. [ 239.248640] upd61151: audio firmware uploading... [ 239.249104] upd61151: Transfer IRQ status 0x1 [ 239.250593] fw upload start [ 239.274165] upd61151: Transfer IRQ status 0x2 [ 246.764126] upd61151: Transfer IRQ status 0x1 [ 246.764312] fw upload stop [ 246.764496] upd61151: audio firmware upload complete... [ 246.764691] upd61151: IRQ status 0x19 [ 246.764876] DEBUG uPD61151: upd61151_chip_command [ 246.765065] upd61151: IRQ error status 0x0 [ 246.765441] upd61151: MPEG2 core status 0 [ 246.765627] upd61151: IRQ error status 0x0 [ 246.776267] upd61151: MPEG2 core status 1 [ 246.776461] upd61151: IRQ status 0x8 [ 246.776647] upd61151: SetState(1) SUCCESS!!! Delay [10 ms]. [ 246.776649] upd61151_setup_video_frontend [ 246.776650] 0x0 0x0 [ 246.777791] upd61151_setup_audio_frontend [ 246.778210] upd61151_config_encoder [ 246.778212] Video attrib1 = 0x80 [ 246.778587] upd61151_prepare_bitrates [ 246.780783] upd61151_set_state [ 246.780996] upd61151: IRQ error status 0x0 [ 246.781448] upd61151: MPEG2 core status 1 [ 246.781633] upd61151: IRQ error status 0x0 [ 246.783822] upd61151: MPEG2 core status 1 [ 246.784023] upd61151: IRQ error status 0x0 [ 246.786210] upd61151: MPEG2 core status 1 [ 246.786395] upd61151: IRQ error status 0x0 [ 246.788608] upd61151: MPEG2 core status 1 [ 246.788800] upd61151: IRQ error status 0x0 [ 246.790990] upd61151: MPEG2 core status 1 [ 246.791182] upd61151: IRQ error status 0x0 [ 246.793369] upd61151: MPEG2 core status 1 [ 246.793554] upd61151: IRQ error status 0x0 [ 246.795740] upd61151: MPEG2 core status 1 [ 246.795925] upd61151: IRQ error status 0x0 [ 246.798114] upd61151: MPEG2 core status 1 [ 246.798299] upd61151: IRQ error status 0x0 [ 246.800486] upd61151: MPEG2 core status 1 [ 246.800671] upd61151: IRQ error status 0x0 [ 246.802863] upd61151: MPEG2 core status 1 [ 246.803070] upd61151: IRQ error status 0x0 [ 246.805261] upd61151: MPEG2 core status 2 [ 246.805447] upd61151: IRQ status 0x28 [ 246.805632] upd61151: MPEG2 SetState(0), SUCCESS! Delay(20 ms) [ 246.805633] DEBUG uPD61151: upd61151_chip_command [ 246.805818] upd61151: IRQ error status 0x0 [ 246.806361] upd61151: MPEG2 core status 2 [ 246.806546] upd61151: IRQ error status 0x0 [ 246.817221] upd61151: MPEG2 core status 1 [ 246.817419] upd61151: IRQ status 0x8 [ 246.817604] upd61151: SetState(1) SUCCESS!!! Delay [10 ms]. [ 246.817606] Firmware downloaded SUCCESS!!! [ 246.817613] saa7134 0000:04:01.0: registered child spi32766.0 [ 246.818333] saa7133[0]: registered device video0 [v4l2] [ 246.818742] saa7133[0]: registered device vbi0 [ 246.818932] saa7133[0]: registered device radio0 [ 246.818934] befor request_submodules [ 246.818940] request_mod_async [ 246.818941] request mod empress [ 246.834515] sap [ 246.835857] sap [ 246.835995] sap [ 246.842066] xc5000: I2C write failed (len=4) [ 246.844303] saa7134_ts_register start [ 246.844306] SAA7134_MPEG_EMPRESS found [ 246.844307] mpeg_ops_attach start [ 246.844308] saa7134_ts_register stop [ 246.844399] dvb = 2 [ 246.844400] request mod dvb [ 246.908378] call saa7134_ts_register [ 246.908381] saa7134_ts_register start [ 246.908382] SAA7134_MPEG_DVB found [ 246.908384] dvb_ops_attach start [ 246.908385] saa7134_ts_register stop [ 246.926959] saa7134 ALSA driver for DMA sound loaded [ 246.926989] saa7133[0]/alsa: saa7133[0] at 0xe5100000 irq 19 registered as card -1 [ 246.943022] xc5000: I2C write failed (len=4) [ 246.943030] DEBUG uPD61151: upd61151_s_std [ 246.943032] DEBUG uPD61151: upd61151_s_std [ 246.944772] xc5000: I2C read failed [ 246.944780] xc5000: I2C read failed [ 246.944782] xc5000: waiting for firmware upload (dvb-fe-xc5000-1.6.114.fw)... [ 246.955952] sap [ 246.985343] xc5000: firmware read 12401 bytes. [ 246.985345] xc5000: firmware uploading... [ 249.048010] xc5000: firmware upload complete... [ 249.689016] DEBUG uPD61151: upd61151_s_std [ 249.689021] DEBUG uPD61151: upd61151_s_std [ 249.693931] sap [ 249.696850] sap [ 250.080015] DEBUG uPD61151: upd61151_s_std [ 250.080020] DEBUG uPD61151: upd61151_s_std [ 250.470016] DEBUG uPD61151: upd61151_s_std [ 250.470021] DEBUG uPD61151: upd61151_s_std With my best regards, Dmitry. commit cb57f465d8c395b66898e49f1dc4f3e7bd01a2e8 Author: dimon Date: Tue May 31 08:27:47 2011 +1000 test commit diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index aa1b2e8..ab8c479 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -383,6 +383,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, u16 VideoMode, u16 AudioMode) { int ret; + dprintk(1, "%s()\n", __func__); dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode); dprintk(1, "%s() Standard = %s\n", __func__, @@ -397,6 +398,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) { + dprintk(1, "%s()\n", __func__); dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE"); @@ -433,6 +435,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz) { u32 freq_code = (freq_khz * 1024)/1000; + dprintk(1, "%s()\n", __func__); dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n", __func__, freq_khz, freq_code); @@ -442,6 +445,8 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz) static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope) { + dprintk(1, "%s()\n", __func__); + return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope); } @@ -451,6 +456,8 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) u16 regData; u32 tmp; + dprintk(1, "%s()\n", __func__); + result = xc5000_readreg(priv, XREG_FREQ_ERROR, ®Data); if (result != XC_RESULT_SUCCESS) return result; @@ -462,6 +469,8 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status) { + dprintk(1, "%s()\n", __func__); + return xc5000_readreg(priv, XREG_LOCK, lock_status); } @@ -472,6 +481,8 @@ static int xc_get_version(struct xc5000_priv *priv, u16 data; int result; + dprintk(1, "%s()\n", __func__); + result = xc5000_readreg(priv, XREG_VERSION, &data); if (result != XC_RESULT_SUCCESS) return result; @@ -486,6 +497,8 @@ static int xc_get_version(struct xc5000_priv *priv, static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev) { + dprintk(1, "%s()\n", __func__); + return xc5000_readreg(priv, XREG_BUILD, buildrev); } @@ -494,6 +507,8 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) u16 regData; int result; + dprintk(1, "%s()\n", __func__); + result = xc5000_readreg(priv, XREG_HSYNC_FREQ, ®Data); if (result != XC_RESULT_SUCCESS) return result; @@ -504,11 +519,15 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines) { + dprintk(1, "%s()\n", __func__); + return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines); } static int xc_get_quality(struct xc5000_priv *priv, u16 *quality) { + dprintk(1, "%s()\n", __func__); + return xc5000_readreg(priv, XREG_QUALITY, quality); } @@ -517,6 +536,8 @@ static u16 WaitForLock(struct xc5000_priv *priv) u16 lockState = 0; int watchDogCount = 40; + dprintk(1, "%s()\n", __func__); + while ((lockState == 0) && (watchDogCount > 0)) { xc_get_lock_status(priv, &lockState); if (lockState != 1) { @@ -552,7 +573,7 @@ static int xc5000_fwupload(struct dvb_frontend *fe) struct xc5000_priv *priv = fe->tuner_priv; const struct firmware *fw; int ret; - + dprintk(1, "%s()\n", __func__); /* request the firmware, this will block and timeout */ printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", XC5000_DEFAULT_FIRMWARE); @@ -642,6 +663,8 @@ static int xc5000_set_params(struct dvb_frontend *fe, { struct xc5000_priv *priv = fe->tuner_priv; int ret; +printk("sp\n"); +// dprintk(1, "%s()\n", __func__); if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { @@ -772,6 +795,8 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe) int ret; u16 id; +// dprintk(1, "%s()\n", __func__); + ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id); if (ret == XC_RESULT_SUCCESS) { if (id == XC_PRODUCT_ID_FW_NOT_LOADED) @@ -790,7 +815,7 @@ static int xc5000_set_tv_freq(struct dvb_frontend *fe, { struct xc5000_priv *priv = fe->tuner_priv; int ret; - + dprintk(1, "%s()\n", __func__); dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", __func__, params->frequency); @@ -878,7 +903,7 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe, struct xc5000_priv *priv = fe->tuner_priv; int ret = -EINVAL; u8 radio_input; - + dprintk(1, "%s()\n", __func__); dprintk(1, "%s() frequency=%d (in units of khz)\n", __func__, params->frequency); @@ -935,14 +960,17 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, { struct xc5000_priv *priv = fe->tuner_priv; int ret = -EINVAL; +printk("sap\n"); + mutex_lock(&xc5000_list_mutex); +// dprintk(1, "%s()\n", __func__); if (priv->i2c_props.adap == NULL) - return -EINVAL; + goto errexit; if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { dprintk(1, "Unable to load firmware and init tuner\n"); - return -EINVAL; + goto errexit; } } @@ -956,7 +984,12 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, break; } + mutex_unlock(&xc5000_list_mutex); return ret; + +errexit: + mutex_unlock(&xc5000_list_mutex); + return -EINVAL; } @@ -982,6 +1015,8 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status) struct xc5000_priv *priv = fe->tuner_priv; u16 lock_status = 0; + dprintk(1, "%s()\n", __func__); + xc_get_lock_status(priv, &lock_status); dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status); @@ -996,6 +1031,10 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) struct xc5000_priv *priv = fe->tuner_priv; int ret = 0; + dprintk(1, "%s()\n", __func__); + +// mutex_lock(&xc5000_list_mutex); + if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { ret = xc5000_fwupload(fe); if (ret != XC_RESULT_SUCCESS) @@ -1015,6 +1054,8 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) /* Default to "CABLE" mode */ ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); +// mutex_unlock(&xc5000_list_mutex); + return ret; } diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index 8a5ff4d..d698ddc 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile @@ -1,10 +1,10 @@ saa7134-y := saa7134-cards.o saa7134-core.o saa7134-i2c.o saa7134-y += saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o -saa7134-y += saa7134-video.o +saa7134-y += saa7134-video.o saa7134-spi.o saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o -obj-$(CONFIG_VIDEO_SAA7134) += saa6752hs.o saa7134.o saa7134-empress.o +obj-$(CONFIG_VIDEO_SAA7134) += saa6752hs.o saa7134.o saa7134-empress.o upd61151.o obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 61c6007..83a0622 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5347,24 +5347,43 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .mpeg = SAA7134_MPEG_DVB, + .mpeg = (SAA7134_MPEG_EMPRESS | SAA7134_MPEG_DVB), + .encoder_type = SAA7134_ENCODER_muPD61151, + .gpiomask = 0x00860000, .inputs = { { .name = name_tv, .vmux = 2, .amux = TV, .tv = 1, + .gpio = 0x00860000 }, { .name = name_comp1, .vmux = 0, .amux = LINE1, + .gpio = 0x00860000 }, { .name = name_svideo, .vmux = 9, .amux = LINE1, + .gpio = 0x00860000 } }, .radio = { .name = name_radio, .amux = TV, + .gpio = 0x00860000 + }, + .video_out = CCIR656, + .vid_port_opts = (SET_T_CODE_POLARITY_NON_INVERTED | + SET_CLOCK_NOT_DELAYED | + SET_CLOCK_INVERTED | + SET_VSYNC_OFF), + .spi = { + .cs = 17, + .clock = 18, + .mosi = 23, + .miso = 21, + .num_chipselect = 1, + .spi_enable = 1, }, }, [SAA7134_BOARD_ZOLID_HYBRID_PCI] = { diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 41f836f..b5bb0af 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -140,6 +140,17 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value) } } +u32 saa7134_get_gpio(struct saa7134_dev *dev) +{ + unsigned long status; + + /* rising SAA7134_GPIO_GPRESCAN reads the status */ + saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,0); + saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,SAA7134_GPIO_GPRESCAN); + status = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & 0xfffffff; + return status; +} + /* ------------------------------------------------------------------ */ @@ -150,10 +161,18 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value) static void request_module_async(struct work_struct *work){ struct saa7134_dev* dev = container_of(work, struct saa7134_dev, request_module_wk); +printk("request_mod_async\n"); if (card_is_empress(dev)) + { + printk("request mod empress\n"); request_module("saa7134-empress"); + } +printk("dvb = %d\n", card_is_dvb(dev)); if (card_is_dvb(dev)) + { + printk("request mod dvb\n"); request_module("saa7134-dvb"); + } if (alsa) { if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130) request_module("saa7134-alsa"); @@ -836,15 +855,54 @@ static void mpeg_ops_attach(struct saa7134_mpeg_ops *ops, struct saa7134_dev *dev) { int err; - +printk("mpeg_ops_attach start\n"); +#if 0 if (NULL != dev->mops) + { + printk("mpeg_ops_attach FAIL stop, mops already exist FAILURE\n"); return; - if (saa7134_boards[dev->board].mpeg != ops->type) + } + if ( !(saa7134_boards[dev->board].mpeg & ops->type)) + { + printk("mpeg_ops_attach FAIL stop, type FAILURE\n"); return; + } err = ops->init(dev); if (0 != err) + { + printk("mpeg_ops_attach FAIL stop, init FAILURE\n"); return; + } +printk("mpeg_ops_attach OK stop\n"); dev->mops = ops; +#endif +} + +static void dvb_ops_attach(struct saa7134_mpeg_ops *ops, + struct saa7134_dev *dev) +{ + int err; +printk("dvb_ops_attach start\n"); +#if 0 + if (NULL != dev->dops) + { + printk("dvb_ops_attach FAIL stop, mops already exist FAILURE\n"); + return; + } + if ( !(saa7134_boards[dev->board].mpeg & ops->type)) + { + printk("dvb_ops_attach FAIL stop, type FAILURE\n"); + return; + } + err = ops->init(dev); + if (0 != err) + { + printk("dvb_ops_attach FAIL stop, init FAILURE\n"); + return; + } +printk("dvb_ops_attach OK stop\n"); + dev->dops = ops; +#endif } static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops, @@ -858,13 +916,29 @@ static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops, dev->mops = NULL; } +static void dvb_ops_detach(struct saa7134_mpeg_ops *ops, + struct saa7134_dev *dev) +{ + if (NULL == dev->dops) + return; + if (dev->dops != ops) + return; + dev->dops->fini(dev); + dev->dops = NULL; +} + static int __devinit saa7134_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct saa7134_dev *dev; struct saa7134_mpeg_ops *mops; + struct saa7134_mpeg_ops *dops; int err; +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) + struct spi_board_info spi_conf; +#endif + if (saa7134_devcount == SAA7134_MAXBOARDS) return -ENOMEM; @@ -1004,12 +1078,61 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, saa7134_hwinit2(dev); - /* load i2c helpers */ +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) + /* initialize software SPI bus */ + if (saa7134_boards[dev->board].spi.spi_enable) + { + switch (dev->board) + { + case SAA7134_BOARD_BEHOLD_X7: + strlcpy(spi_conf.modalias, "upd61151", sizeof(spi_conf.modalias)); + spi_conf.max_speed_hz = 50000000; + spi_conf.chip_select = 0; + spi_conf.mode = SPI_MODE_0; + spi_conf.controller_data = NULL; + spi_conf.platform_data = NULL; + break; + } + + dev->spi = saa7134_boards[dev->board].spi; + + /* register SPI master and SPI slave */ + if (saa7134_spi_register(dev, &spi_conf)) + saa7134_boards[dev->board].spi.spi_enable = 0; + } +#endif + + /* load bus helpers */ if (card_is_empress(dev)) { - struct v4l2_subdev *sd = - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + struct v4l2_subdev *sd = NULL; + + dev->encoder_type = saa7134_boards[dev->board].encoder_type; + + switch (dev->encoder_type) { + case SAA7134_ENCODER_muPD61151: + { + printk(KERN_INFO "%s: found muPD61151 MPEG encoder\n", dev->name); + +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) + if (saa7134_boards[dev->board].spi.spi_enable) + sd = v4l2_spi_new_subdev(&dev->v4l2_dev, dev->spi_adap, &spi_conf); +#else + printk(KERN_INFO "%s: You can't use muPD61151 MPEG2 encoder. SPI subsystem not included into kernel.\n", dev->name); +#endif + + } + break; + case SAA7134_ENCODER_SAA6752HS: + { + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "saa6752hs", saa7134_boards[dev->board].empress_addr, NULL); + } + break; + default: + printk(KERN_INFO "%s: MPEG encoder is not configured\n", dev->name); + break; + } if (sd) sd->grp_id = GRP_EMPRESS; @@ -1032,6 +1155,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, mutex_lock(&saa7134_devlist_lock); list_for_each_entry(mops, &mops_list, next) mpeg_ops_attach(mops, dev); +// list_add_tail(&dev->devlist, &saa7134_devlist); + list_for_each_entry(dops, &mops_list, next) + dvb_ops_attach(dops, dev); list_add_tail(&dev->devlist, &saa7134_devlist); mutex_unlock(&saa7134_devlist_lock); @@ -1080,11 +1206,15 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (saa7134_dmasound_init && !dev->dmasound.priv_data) saa7134_dmasound_init(dev); - +printk("befor request_submodules\n"); request_submodules(dev); return 0; fail4: +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) + if ((card_is_empress(dev)) && (dev->encoder_type == SAA7134_ENCODER_muPD61151)) + saa7134_spi_unregister(dev); +#endif saa7134_unregister_video(dev); saa7134_i2c_unregister(dev); free_irq(pci_dev->irq, dev); @@ -1106,6 +1236,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev); struct saa7134_mpeg_ops *mops; + struct saa7134_mpeg_ops *dops; flush_request_submodules(dev); @@ -1137,6 +1268,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) list_del(&dev->devlist); list_for_each_entry(mops, &mops_list, next) mpeg_ops_detach(mops, dev); + list_for_each_entry(dops, &mops_list, next) + dvb_ops_detach(dops, dev); mutex_unlock(&saa7134_devlist_lock); saa7134_devcount--; @@ -1293,12 +1426,24 @@ static int saa7134_resume(struct pci_dev *pci_dev) int saa7134_ts_register(struct saa7134_mpeg_ops *ops) { struct saa7134_dev *dev; - - mutex_lock(&saa7134_devlist_lock); - list_for_each_entry(dev, &saa7134_devlist, devlist) - mpeg_ops_attach(ops, dev); - list_add_tail(&ops->next,&mops_list); - mutex_unlock(&saa7134_devlist_lock); +printk("saa7134_ts_register start\n"); + if (ops -> type == SAA7134_MPEG_EMPRESS) { + printk("SAA7134_MPEG_EMPRESS found\n"); + mutex_lock(&saa7134_devlist_lock); + list_for_each_entry(dev, &saa7134_devlist, devlist) + mpeg_ops_attach(ops, dev); + list_add_tail(&ops->next,&mops_list); + mutex_unlock(&saa7134_devlist_lock); + } + if (ops -> type == SAA7134_MPEG_DVB) { + printk("SAA7134_MPEG_DVB found\n"); + mutex_lock(&saa7134_devlist_lock); + list_for_each_entry(dev, &saa7134_devlist, devlist) + dvb_ops_attach(ops, dev); + list_add_tail(&ops->next,&mops_list); + mutex_unlock(&saa7134_devlist_lock); + } +printk("saa7134_ts_register stop\n"); return 0; } @@ -1306,11 +1451,20 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops) { struct saa7134_dev *dev; - mutex_lock(&saa7134_devlist_lock); - list_del(&ops->next); - list_for_each_entry(dev, &saa7134_devlist, devlist) - mpeg_ops_detach(ops, dev); - mutex_unlock(&saa7134_devlist_lock); + if (ops -> type == SAA7134_MPEG_EMPRESS) { + mutex_lock(&saa7134_devlist_lock); + list_del(&ops->next); + list_for_each_entry(dev, &saa7134_devlist, devlist) + mpeg_ops_detach(ops, dev); + mutex_unlock(&saa7134_devlist_lock); + } + if (ops -> type == SAA7134_MPEG_DVB) { + mutex_lock(&saa7134_devlist_lock); + list_del(&ops->next); + list_for_each_entry(dev, &saa7134_devlist, devlist) + dvb_ops_detach(ops, dev); + mutex_unlock(&saa7134_devlist_lock); + } } EXPORT_SYMBOL(saa7134_ts_register); @@ -1354,6 +1508,7 @@ module_exit(saa7134_fini); /* ----------------------------------------------------------- */ EXPORT_SYMBOL(saa7134_set_gpio); +EXPORT_SYMBOL(saa7134_get_gpio); EXPORT_SYMBOL(saa7134_boards); /* ----------------- for the DMA sound modules --------------- */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index f65cad2..d9438e3 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -938,6 +938,41 @@ static struct zl10353_config behold_x7_config = { .disable_i2c_gate_ctrl = 1, }; +static int zl10353_dvb_bus_ctrl_behold_x7(struct dvb_frontend *fe, int acquire) { + struct saa7134_dev *dev = fe->dvb->priv; + static u8 zl10353_ts_enable[] = { 0x50, 0x03}; + static u8 zl10353_ts_disable[] = { 0x50, 0x05}; + struct i2c_msg zl10353_msg = {.addr = behold_x7_config.demod_address, + .flags = 0, .len = 2}; + +printk("zl10353_dvb_bus_ctrl() acquire = %d\n",acquire); + + if (acquire) + { + zl10353_msg.buf = zl10353_ts_enable; + dev->ts.mpeg = SAA7134_MPEG_DVB; + saa7134_boards[dev->board].ts_type = SAA7134_MPEG_TS_PARALLEL; +printk("set SAA7134_MPEG_DVB\n"); + } + else + { + zl10353_msg.buf = zl10353_ts_disable; + dev->ts.mpeg = SAA7134_MPEG_EMPRESS; + saa7134_boards[dev->board].ts_type = SAA7134_MPEG_PS_PARALLEL; +printk("set SAA7134_MPEG_EMPRESS\n"); + } + + /* Switch TS bus of the zl10353 */ + if (i2c_transfer(&dev->i2c_adap, &zl10353_msg, 1) != 1) { + wprintk("could not access zl10353 TS bus gate control\n"); + return -EIO; + } + + msleep(10); + + return 0; +} + /* ================================================================== * tda10086 based DVB-S cards, helper functions */ @@ -1132,18 +1167,18 @@ static int dvb_init(struct saa7134_dev *dev) int ret; int attach_xc3028 = 0; struct videobuf_dvb_frontend *fe0; - +printk("saa7134-dvb init start\n"); /* FIXME: add support for multi-frontend */ mutex_init(&dev->frontends.lock); INIT_LIST_HEAD(&dev->frontends.felist); - +printk("befor dvb_alloc_frontend\n"); printk(KERN_INFO "%s() allocating 1 frontend\n", __func__); fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1); if (!fe0) { printk(KERN_ERR "%s() failed to alloc\n", __func__); return -ENOMEM; } - +printk("befor videobuf_dvb\n"); /* init struct videobuf_dvb */ dev->ts.nr_bufs = 32; dev->ts.nr_packets = 32*4; @@ -1154,7 +1189,7 @@ static int dvb_init(struct saa7134_dev *dev) V4L2_FIELD_ALTERNATE, sizeof(struct saa7134_buf), dev, NULL); - +printk("befor switch dev->board\n"); switch (dev->board) { case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: dprintk("pinnacle 300i dvb setup\n"); @@ -1592,6 +1627,7 @@ static int dvb_init(struct saa7134_dev *dev) fe0->dvb.frontend = dvb_attach(zl10353_attach, &behold_x7_config, &dev->i2c_adap); + printk("dvb.frontend = %p\n", fe0->dvb.frontend); if (fe0->dvb.frontend) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &dev->i2c_adap, &behold_x7_tunerconfig); @@ -1602,6 +1638,7 @@ static int dvb_init(struct saa7134_dev *dev) &behold_x7_config, &dev->i2c_adap); if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.ts_bus_ctrl = zl10353_dvb_bus_ctrl_behold_x7; dvb_attach(xc5000_attach, fe0->dvb.frontend, &dev->i2c_adap, &behold_x7_tunerconfig); } @@ -1719,10 +1756,12 @@ static int dvb_init(struct saa7134_dev *dev) if (fe0->dvb.frontend->ops.tuner_ops.sleep) fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend); } +printk("saa7134-dvb init OK stop\n"); return ret; dettach_frontend: videobuf_dvb_dealloc_frontends(&dev->frontends); +printk("saa7134-dvb init FAIL stop\n"); return -EINVAL; } @@ -1774,6 +1813,7 @@ static struct saa7134_mpeg_ops dvb_ops = { static int __init dvb_register(void) { +printk("call saa7134_ts_register\n"); return saa7134_ts_register(&dvb_ops); } diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 18294db..2f9d4f8 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -51,6 +51,7 @@ MODULE_PARM_DESC(debug,"enable debug messages"); static void ts_reset_encoder(struct saa7134_dev* dev) { +printk("ts_reset_encoder() start\n"); if (!dev->empress_started) return; @@ -59,12 +60,13 @@ static void ts_reset_encoder(struct saa7134_dev* dev) saa_writeb(SAA7134_SPECIAL_MODE, 0x01); msleep(100); dev->empress_started = 0; +printk("ts_reset_encoder() stop\n"); } static int ts_init_encoder(struct saa7134_dev* dev) { u32 leading_null_bytes = 0; - +printk("ts_init_encoder() start\n"); /* If more cards start to need this, then this should probably be added to the card definitions. */ switch (dev->board) { @@ -77,6 +79,7 @@ static int ts_init_encoder(struct saa7134_dev* dev) ts_reset_encoder(dev); saa_call_all(dev, core, init, leading_null_bytes); dev->empress_started = 1; +printk("ts_init_encoder() stop\n"); return 0; } @@ -87,7 +90,7 @@ static int ts_open(struct file *file) struct video_device *vdev = video_devdata(file); struct saa7134_dev *dev = video_drvdata(file); int err; - +printk("ts_open() start\n"); dprintk("open dev=%s\n", video_device_node_name(vdev)); err = -EBUSY; if (!mutex_trylock(&dev->empress_tsq.vb_lock)) @@ -105,13 +108,14 @@ static int ts_open(struct file *file) done: mutex_unlock(&dev->empress_tsq.vb_lock); +printk("ts_open() stop\n"); return err; } static int ts_release(struct file *file) { struct saa7134_dev *dev = file->private_data; - +printk("ts_release() start\n"); videobuf_stop(&dev->empress_tsq); videobuf_mmap_free(&dev->empress_tsq); @@ -123,7 +127,7 @@ static int ts_release(struct file *file) saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); atomic_dec(&dev->empress_users); - +printk("ts_release() stop\n"); return 0; } @@ -167,7 +171,7 @@ static int empress_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct saa7134_dev *dev = file->private_data; - +printk("empress_querycap() start\n"); strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); @@ -177,44 +181,49 @@ static int empress_querycap(struct file *file, void *priv, V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; +printk("empress_querycap() stop\n"); return 0; } static int empress_enum_input(struct file *file, void *priv, struct v4l2_input *i) { +printk("empress_enum_input() start\n"); if (i->index != 0) return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, "CCIR656"); - +printk("empress_enum_input() stop\n"); return 0; } static int empress_g_input(struct file *file, void *priv, unsigned int *i) { *i = 0; +printk("empress_g_input() start\n"); return 0; } static int empress_s_input(struct file *file, void *priv, unsigned int i) { +printk("empress_s_input() start\n"); if (i != 0) return -EINVAL; - +printk("empress_s_input() stop\n"); return 0; } static int empress_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { +printk("empress_enum_fmt_vid_cap() start\n"); if (f->index != 0) return -EINVAL; strlcpy(f->description, "MPEG TS", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; - +printk("empress_enum_fmt_vid_cap() stop\n"); return 0; } @@ -223,13 +232,13 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv, { struct saa7134_dev *dev = file->private_data; struct v4l2_mbus_framefmt mbus_fmt; - +printk("empress_g_fmt_vid_cap() start\n"); saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt); v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; - +printk("empress_g_fmt_vid_cap() stop\n"); return 0; } @@ -238,14 +247,14 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv, { struct saa7134_dev *dev = file->private_data; struct v4l2_mbus_framefmt mbus_fmt; - +printk("empress_s_fmt_vid_cap() start\n"); v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt); v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; - +printk("empress_s_fmt_vid_cap() stop\n"); return 0; } @@ -253,10 +262,10 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_dev *dev = file->private_data; - +printk("empress_try_fmt_vid_cap() start\n"); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; - +printk("empress_try_fmt_vid_cap() stop\n"); return 0; } @@ -264,7 +273,7 @@ static int empress_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { struct saa7134_dev *dev = file->private_data; - +printk("empress_reqbufs()\n"); return videobuf_reqbufs(&dev->empress_tsq, p); } @@ -272,21 +281,21 @@ static int empress_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) { struct saa7134_dev *dev = file->private_data; - +printk("empress_querybuf()\n"); return videobuf_querybuf(&dev->empress_tsq, b); } static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) { struct saa7134_dev *dev = file->private_data; - +printk("empress_qbuf()\n"); return videobuf_qbuf(&dev->empress_tsq, b); } static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) { struct saa7134_dev *dev = file->private_data; - +printk("empress_dqbuf()\n"); return videobuf_dqbuf(&dev->empress_tsq, b, file->f_flags & O_NONBLOCK); } @@ -295,7 +304,7 @@ static int empress_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct saa7134_dev *dev = file->private_data; - +printk("empress_streamon()\n"); return videobuf_streamon(&dev->empress_tsq); } @@ -303,7 +312,7 @@ static int empress_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { struct saa7134_dev *dev = file->private_data; - +printk("empress_streamoff()\n"); return videobuf_streamoff(&dev->empress_tsq); } @@ -312,7 +321,7 @@ static int empress_s_ext_ctrls(struct file *file, void *priv, { struct saa7134_dev *dev = file->private_data; int err; - +printk("empress_s_ext_ctrls() start\n"); /* count == 0 is abused in saa6752hs.c, so that special case is handled here explicitly. */ if (ctrls->count == 0) @@ -323,7 +332,7 @@ static int empress_s_ext_ctrls(struct file *file, void *priv, err = saa_call_empress(dev, core, s_ext_ctrls, ctrls); ts_init_encoder(dev); - +printk("empress_s_ext_ctrls() stop\n"); return err; } @@ -331,9 +340,10 @@ static int empress_g_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { struct saa7134_dev *dev = file->private_data; - +printk("empress_g_ext_ctrls() start\n"); if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; +printk("empress_g_ext_ctrls() stop\n"); return saa_call_empress(dev, core, g_ext_ctrls, ctrls); } @@ -341,7 +351,7 @@ static int empress_g_ctrl(struct file *file, void *priv, struct v4l2_control *c) { struct saa7134_dev *dev = file->private_data; - +printk("empress_g_ctrl()\n"); return saa7134_g_ctrl_internal(dev, NULL, c); } @@ -349,13 +359,14 @@ static int empress_s_ctrl(struct file *file, void *priv, struct v4l2_control *c) { struct saa7134_dev *dev = file->private_data; - +printk("empress_s_ctrl()\n"); return saa7134_s_ctrl_internal(dev, NULL, c); } static int empress_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c) { +printk("empress_queryctrl() start\n"); /* Must be sorted from low to high control ID! */ static const u32 user_ctrls[] = { V4L2_CID_USER_CLASS, @@ -401,6 +412,7 @@ static int empress_queryctrl(struct file *file, void *priv, return v4l2_ctrl_query_fill(c, 0, 0, 0, 0); if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG) return saa7134_queryctrl(file, priv, c); +printk("empress_queryctrl() stop\n"); return saa_call_empress(dev, core, queryctrl, c); } @@ -408,9 +420,10 @@ static int empress_querymenu(struct file *file, void *priv, struct v4l2_querymenu *c) { struct saa7134_dev *dev = file->private_data; - +printk("empress_querymenu() start\n"); if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG) return -EINVAL; +printk("empress_querymenu() stop\n"); return saa_call_empress(dev, core, querymenu, c); } @@ -418,7 +431,7 @@ static int empress_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip) { struct saa7134_dev *dev = file->private_data; - +printk("empress_g_chip_ident() start\n"); chip->ident = V4L2_IDENT_NONE; chip->revision = 0; if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER && @@ -426,20 +439,21 @@ static int empress_g_chip_ident(struct file *file, void *fh, return saa_call_empress(dev, core, g_chip_ident, chip); if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR) return saa_call_empress(dev, core, g_chip_ident, chip); ++printk("empress_g_chip_ident() stop FAIL\n"); return -EINVAL; } static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id) { struct saa7134_dev *dev = file->private_data; - +printk("empress_s_std()\n"); return saa7134_s_std_internal(dev, NULL, id); } static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id) { struct saa7134_dev *dev = file->private_data; - +printk("empress_g_std()\n"); *id = dev->tvnorm->id; return 0; } diff --git a/drivers/media/video/saa7134/saa7134-spi.c b/drivers/media/video/saa7134/saa7134-spi.c new file mode 100644 index 0000000..35a1eaa --- /dev/null +++ b/drivers/media/video/saa7134/saa7134-spi.c @@ -0,0 +1,159 @@ +/* + * + * Device driver for philips saa7134 based TV cards + * SPI software interface support + * + * (c) 2009 Beholder Intl. Ltd. Dmitry Belimov + * + * Important: now support ONLY SPI_MODE_0, see FIXME + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) + +#include "saa7134-reg.h" +#include "saa7134.h" +#include + +/* ----------------------------------------------------------- */ + +static unsigned int spi_debug; +module_param(spi_debug, int, 0644); +MODULE_PARM_DESC(spi_debug,"enable debug messages [spi]"); + +#define d1printk if (1 == spi_debug) printk +#define d2printk if (2 == spi_debug) printk + +static inline void spidelay(unsigned d) +{ + ndelay(d); +} + +static inline struct saa7134_spi_gpio *to_sb(struct spi_device *spi) +{ + return spi_master_get_devdata(spi->master); +} + +static inline void setsck(struct spi_device *dev, int on) +{ + struct saa7134_spi_gpio *sb = to_sb(dev); + + saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.clock, on ? 1 : 0); +} + +static inline void setmosi(struct spi_device *dev, int on) +{ + struct saa7134_spi_gpio *sb = to_sb(dev); + + saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.mosi, on ? 1 : 0); +} + +static inline u32 getmiso(struct spi_device *dev) +{ + struct saa7134_spi_gpio *sb = to_sb(dev); + unsigned long status; + + status = saa7134_get_gpio(sb->controller_data); + return !!( status & (1 << sb->controller_data->spi.miso)); +} + +#define EXPAND_BITBANG_TXRX 1 +#include +#include +#include "spi_bitbang_txrx.h" + +static void saa7134_spi_gpio_chipsel(struct spi_device *dev, int on) +{ + struct saa7134_spi_gpio *sb = to_sb(dev); + + if (on) + { + /* FIXME: set clock to zero by default, only SPI_MODE_0 compatible */ + saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.clock, 0); + saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.cs, 0); + } + else + saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.cs, 1); +} + +/* Our actual bitbanger routine. */ +static u32 saa7134_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); +} + +int saa7134_spi_register(struct saa7134_dev *dev, struct spi_board_info *info) +{ + struct spi_master *master = NULL; + struct saa7134_spi_gpio *sb = NULL; + int ret = 0; + + master = spi_alloc_master(&dev->pci->dev, sizeof(struct saa7134_spi_gpio)); + + if (master == NULL) + { + dev_err(&dev->pci->dev, "failed to allocate spi master\n"); + ret = -ENOMEM; + goto err; + } + + sb = spi_master_get_devdata(master); + + master->num_chipselect = dev->spi.num_chipselect; + master->bus_num = -1; + sb->master = spi_master_get(master); + sb->bitbang.master = sb->master; + sb->bitbang.master->bus_num = -1; + sb->bitbang.master->num_chipselect = dev->spi.num_chipselect; + sb->bitbang.chipselect = saa7134_spi_gpio_chipsel; + sb->bitbang.txrx_word[SPI_MODE_0] = saa7134_txrx; + + /* set state of spi pins */ + saa7134_set_gpio(dev, dev->spi.cs, 1); + /* FIXME: set clock to zero by default, only SPI_MODE_0 compatible */ + saa7134_set_gpio(dev, dev->spi.clock, 0); + saa7134_set_gpio(dev, dev->spi.mosi, 1); + saa7134_set_gpio(dev, dev->spi.miso, 3); + + /* start SPI bitbang master */ + ret = spi_bitbang_start(&sb->bitbang); + if (ret) { + dev_err(&dev->pci->dev, "Failed to register SPI master\n"); + goto err_no_bitbang; + } + dev_info(&dev->pci->dev, + "spi master registered: bus_num=%d num_chipselect=%d\n", + master->bus_num, master->num_chipselect); + + sb->controller_data = dev; + info->bus_num = sb->master->bus_num; + info->controller_data = master; + dev->spi_adap = master; + +err_no_bitbang: + spi_master_put(master); +err: + return ret; +} + +void saa7134_spi_unregister(struct saa7134_dev *dev) +{ + struct saa7134_spi_gpio *sb = spi_master_get_devdata(dev->spi_adap); + + spi_bitbang_stop(&sb->bitbang); + spi_master_put(sb->master); +} + +#endif diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index 2e3f4b4..9df27fb 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -85,6 +85,10 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, llength = TS_PACKET_SIZE; lines = dev->ts.nr_packets; + if (saa7134_boards[dev->board].ts_type == SAA7134_MPEG_PS_PARALLEL) + llength = PS_PACKET_SIZE; +printk("buffer_prepare set llength = %d\n", llength); + size = lines * llength; if (0 != buf->vb.baddr && buf->vb.bsize < size) return -EINVAL; @@ -129,8 +133,14 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { struct saa7134_dev *dev = q->priv_data; + unsigned int psize; + + psize = TS_PACKET_SIZE; + if (saa7134_boards[dev->board].ts_type == SAA7134_MPEG_PS_PARALLEL) + psize = PS_PACKET_SIZE; +printk("buffer_setup set psize = %d\n", psize); + *size = psize * dev->ts.nr_packets; - *size = TS_PACKET_SIZE * dev->ts.nr_packets; if (0 == *count) *count = dev->ts.nr_bufs; *count = saa7134_buffer_count(*size,*count); @@ -178,11 +188,18 @@ MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); int saa7134_ts_init_hw(struct saa7134_dev *dev) { + unsigned int psize; + + psize = TS_PACKET_SIZE; + if (saa7134_boards[dev->board].ts_type == SAA7134_MPEG_PS_PARALLEL) + psize = PS_PACKET_SIZE; +printk("buffer_setup set psize = %d\n", psize); + /* deactivate TS softreset */ saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* TSSOP high active, TSVAL high active, TSLOCK ignored */ saa_writeb(SAA7134_TS_PARALLEL, 0x6c); - saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); + saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (psize - 1)); saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); /* TSNOPIT=0, TSCOLAP=0 */ @@ -238,6 +255,11 @@ int saa7134_ts_stop(struct saa7134_dev *dev) saa_writeb(SAA7134_TS_SERIAL0, 0x40); dev->ts_started = 0; break; + case SAA7134_MPEG_PS_PARALLEL: + printk("Stop SAA7134_MPEG_PS_PARALLEL\n"); + saa_writeb(SAA7134_TS_PARALLEL, 0x5e); + dev->ts_started = 0; + break; } return 0; } @@ -245,10 +267,16 @@ int saa7134_ts_stop(struct saa7134_dev *dev) /* Function for start TS */ int saa7134_ts_start(struct saa7134_dev *dev) { + unsigned int psize; dprintk("TS start\n"); BUG_ON(dev->ts_started); + psize = TS_PACKET_SIZE; + if (saa7134_boards[dev->board].ts_type == SAA7134_MPEG_PS_PARALLEL) + psize = PS_PACKET_SIZE; +printk("buffer_setup set psize = %d\n", psize); + /* dma: setup channel 5 (= TS) */ saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); saa_writeb(SAA7134_TS_DMA1, @@ -256,7 +284,7 @@ int saa7134_ts_start(struct saa7134_dev *dev) /* TSNOPIT=0, TSCOLAP=0 */ saa_writeb(SAA7134_TS_DMA2, (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); - saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); + saa_writel(SAA7134_RS_PITCH(5), psize); saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | SAA7134_RS_CONTROL_ME | (dev->ts.pt_ts.dma >> 12)); @@ -284,10 +312,19 @@ int saa7134_ts_start(struct saa7134_dev *dev) saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc); saa_writeb(SAA7134_TS_SERIAL1, 0x02); break; + case SAA7134_MPEG_PS_PARALLEL: + printk("Start SAA7134_MPEG_PS_PARALLEL\n"); + /* TS clock inverted */ + saa_writeb(SAA7134_TS_SERIAL1, 0x02); + + saa_writeb(SAA7134_TS_SERIAL0, 0x40); + saa_writeb(SAA7134_TS_PARALLEL, 0xde | + (saa7134_boards[dev->board].ts_force_val << 4)); + break; } dev->ts_started = 1; - +printk("start TS HERE \n"); return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f96cd5d..e2fc9e6 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -45,6 +45,11 @@ #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) #include #endif +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) +#include +#include +#include +#endif #define UNSET (-1U) @@ -355,14 +360,30 @@ struct saa7134_input { }; enum saa7134_mpeg_type { - SAA7134_MPEG_UNUSED, - SAA7134_MPEG_EMPRESS, - SAA7134_MPEG_DVB, + SAA7134_MPEG_UNUSED = 0, + SAA7134_MPEG_EMPRESS = 1, + SAA7134_MPEG_DVB = 2, }; enum saa7134_mpeg_ts_type { SAA7134_MPEG_TS_PARALLEL = 0, SAA7134_MPEG_TS_SERIAL, + SAA7134_MPEG_PS_PARALLEL, +}; + +enum saa7134_encoder_type { + SAA7134_ENCODER_UNUSED = 0, + SAA7134_ENCODER_SAA6752HS = 1, + SAA7134_ENCODER_muPD61151 = 2, +}; + +struct saa7134_software_spi { + unsigned char cs:5; + unsigned char clock:5; + unsigned char mosi:5; + unsigned char miso:5; + unsigned char num_chipselect:3; + unsigned char spi_enable:1; }; struct saa7134_board { @@ -383,6 +404,9 @@ struct saa7134_board { unsigned char empress_addr; unsigned char rds_addr; + /* SPI info */ + struct saa7134_software_spi spi; + unsigned int tda9887_conf; unsigned int tuner_config; @@ -390,13 +414,14 @@ struct saa7134_board { enum saa7134_video_out video_out; enum saa7134_mpeg_type mpeg; enum saa7134_mpeg_ts_type ts_type; + enum saa7134_encoder_type encoder_type; unsigned int vid_port_opts; unsigned int ts_force_val:1; }; #define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name) -#define card_is_empress(dev) (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg) -#define card_is_dvb(dev) (SAA7134_MPEG_DVB == saa7134_boards[dev->board].mpeg) +#define card_is_empress(dev) (SAA7134_MPEG_EMPRESS & saa7134_boards[dev->board].mpeg) +#define card_is_dvb(dev) (SAA7134_MPEG_DVB & saa7134_boards[dev->board].mpeg) #define card_has_mpeg(dev) (SAA7134_MPEG_UNUSED != saa7134_boards[dev->board].mpeg) #define card(dev) (saa7134_boards[dev->board]) #define card_in(dev,n) (saa7134_boards[dev->board].inputs[n]) @@ -519,6 +544,7 @@ struct saa7134_ts { struct saa7134_pgtable pt_ts; int nr_packets; int nr_bufs; + enum saa7134_mpeg_type mpeg; }; /* ts/mpeg ops */ @@ -530,6 +556,14 @@ struct saa7134_mpeg_ops { void (*signal_change)(struct saa7134_dev *dev); }; +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) +struct saa7134_spi_gpio { + struct spi_bitbang bitbang; + struct spi_master *master; + struct saa7134_dev *controller_data; +}; +#endif + /* global device status */ struct saa7134_dev { struct list_head devlist; @@ -578,6 +612,12 @@ struct saa7134_dev { unsigned char eedata[256]; int has_rds; + /* software spi */ + struct saa7134_software_spi spi; +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) + struct spi_master *spi_adap; +#endif + /* video overlay */ struct v4l2_framebuffer ovbuf; struct saa7134_format *ovfmt; @@ -637,9 +677,11 @@ struct saa7134_dev { atomic_t empress_users; struct work_struct empress_workqueue; int empress_started; + enum saa7134_encoder_type encoder_type; #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) /* SAA7134_MPEG_DVB only */ + struct saa7134_mpeg_ops *dops; struct videobuf_dvb_frontends frontends; int (*original_demod_sleep)(struct dvb_frontend *fe); int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); @@ -703,6 +745,7 @@ extern int saa7134_no_overlay; void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value); +u32 saa7134_get_gpio(struct saa7134_dev *dev); #define SAA7134_PGTABLE_SIZE 4096 @@ -748,6 +791,13 @@ int saa7134_tuner_callback(void *priv, int component, int command, int arg); int saa7134_i2c_register(struct saa7134_dev *dev); int saa7134_i2c_unregister(struct saa7134_dev *dev); +/* ----------------------------------------------------------- */ +/* saa7134-spi.c */ + +#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG)) +int saa7134_spi_register(struct saa7134_dev *dev, struct spi_board_info *info); +void saa7134_spi_unregister(struct saa7134_dev *dev); +#endif /* ----------------------------------------------------------- */ /* saa7134-video.c */ @@ -774,6 +824,7 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status); /* saa7134-ts.c */ #define TS_PACKET_SIZE 188 /* TS packets 188 bytes */ +#define PS_PACKET_SIZE 128 /* PS packets 128 bytes */ extern struct videobuf_queue_ops saa7134_ts_qops; diff --git a/drivers/media/video/saa7134/upd61151.c b/drivers/media/video/saa7134/upd61151.c new file mode 100644 index 0000000..3c792bd --- /dev/null +++ b/drivers/media/video/saa7134/upd61151.c @@ -0,0 +1,1546 @@ + /* + upd61151 - driver for the uPD61151 by NEC + + Copyright (C) Beholder Intl. Ltd. Dmitry Belimov + + Based on the saa6752s.c driver. + Copyright (C) 2004 Andrew de Quincey + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License vs published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "compat.h" +#include +#include +#include +#include +#include + +#include +#include "saa7134.h" + +#define DRVNAME "upd61151" + +static unsigned int spi_debug; +module_param(spi_debug, int, 0644); +MODULE_PARM_DESC(spi_debug,"enable debug messages [spi]"); + +#define d1printk_spi if (1 <= spi_debug) printk +#define d2printk_spi if (2 <= spi_debug) printk + +static unsigned int core_debug; +module_param(core_debug, int, 0644); +MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); + +#define d1printk_core if (1 <= core_debug) printk +#define d2printk_core if (2 <= core_debug) printk + +MODULE_DESCRIPTION("device driver for uPD61151 MPEG2 encoder"); +MODULE_AUTHOR("Dmitry V Belimov"); +MODULE_LICENSE("GPL"); + +/* Result codes */ +#define RESULT_SUCCESS 0 +#define RESULT_FAILURE 1 +#define STATUS_DEVICE_NOT_READY 2 +#define STATUS_DEVICE_DATA_ERROR 3 +#define STATUS_INVALID_PARAMETER 4 + +enum upd61151_videoformat { + UPD61151_VF_D1 = 0, /* 720x480/720x576 */ + UPD61151_VF_D2 = 1, /* 704x480/704x576 */ + UPD61151_VF_D3 = 2, /* 352x480/352x576 */ + UPD61151_VF_D4 = 3, /* 352x240/352x288 */ + UPD61151_VF_D5 = 4, /* 544x480/544x576 */ + UPD61151_VF_D6 = 5, /* 480x480/480x576 */ + UPD61151_VF_D7 = 6, /* 352x240/352x288 */ + UPD61151_VF_D8 = 8, /* 640x480/640x576 */ + UPD61151_VF_D9 = 9, /* 320x480/320x576 */ + UPD61151_VF_D10 = 10, /* 320x240/320x288 */ + UPD61151_VF_UNKNOWN, +}; + +struct upd61151_mpeg_params { + /* audio */ + enum v4l2_mpeg_audio_sampling_freq au_sampling; + enum v4l2_mpeg_audio_encoding au_encoding; + enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; + + /* video */ + enum v4l2_mpeg_video_aspect vi_aspect; + enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode; + __u32 vi_bitrate; + __u32 vi_bitrate_peak; + + /* encoder */ + u8 video_gop_size; + u8 video_gop_closure; +}; + +static const struct v4l2_format v4l2_format_table[] = +{ + [UPD61151_VF_D1] = + { .fmt = { .pix = { .width = 720, .height = 576 }}}, + [UPD61151_VF_D2] = + { .fmt = { .pix = { .width = 704, .height = 576 }}}, + [UPD61151_VF_D3] = + { .fmt = { .pix = { .width = 352, .height = 576 }}}, + [UPD61151_VF_D4] = + { .fmt = { .pix = { .width = 352, .height = 288 }}}, + [UPD61151_VF_D5] = + { .fmt = { .pix = { .width = 544, .height = 576 }}}, + [UPD61151_VF_D6] = + { .fmt = { .pix = { .width = 480, .height = 576 }}}, + [UPD61151_VF_D7] = + { .fmt = { .pix = { .width = 352, .height = 288 }}}, + [UPD61151_VF_D8] = + { .fmt = { .pix = { .width = 640, .height = 576 }}}, + [UPD61151_VF_D9] = + { .fmt = { .pix = { .width = 320, .height = 576 }}}, + [UPD61151_VF_D10] = + { .fmt = { .pix = { .width = 320, .height = 288 }}}, + [UPD61151_VF_UNKNOWN] = + { .fmt = { .pix = { .width = 0, .height = 0}}}, +}; + +struct upd61151_state { + struct v4l2_subdev sd; + struct upd61151_mpeg_params params; + enum upd61151_videoformat video_format; + v4l2_std_id standard; + enum upd61151_encode_state enstate; +}; + +static struct upd61151_mpeg_params param_defaults = +{ + .vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, + .vi_bitrate = 4000, + .vi_bitrate_peak = 6000, + .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + + .au_sampling = V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, + .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, + + .video_gop_size = 1, + .video_gop_closure = 0, +}; + +static int write_reg(struct spi_device *spi, u8 address, u8 data) +{ + u8 buf[2]; + + buf[0] = ((address >> 2) << 2); + buf[1] = data; + + d2printk_spi(KERN_DEBUG "%s: spi data 0x%x <= 0x%x\n",spi->modalias,address,data); + + return spi_write(spi, buf, ARRAY_SIZE(buf)); +} + +static void write_fw(struct spi_device *spi, u8 address, const struct firmware *fw) +{ + u8 buf[2]; + u32 i; + + buf[0] = ((address >> 2) << 2); + + for (i=0; i < fw->size; i++) + { + buf[1] = *(fw->data+i); + spi_write(spi, buf, 2); + } +} + +static int read_reg(struct spi_device *spi, unsigned char address, unsigned char *data) +{ + u8 buf[1]; + int ret; + + ret = 0; + buf[0] = ((address >> 2) << 2) | 0x02; + ret = spi_write_then_read(spi, buf, 1, data, 1); + + d2printk_spi(KERN_DEBUG "%s: spi data 0x%x => 0x%x, status %d\n",spi->modalias, address, *data, ret); + + return ret; +} + +static void upd61151_reset_core(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + + write_reg(spi, UPD61151_SOFTWARE_RST, 0x01); +} + +static void upd61151_set_dest_addr(struct v4l2_subdev *sd, u32 addr) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + + write_reg(spi, UPD61151_TRANSFER_ADDR1, (u8)((addr >> 16) & 0xFF)); + write_reg(spi, UPD61151_TRANSFER_ADDR2, (u8)((addr >> 8) & 0xFF)); + write_reg(spi, UPD61151_TRANSFER_ADDR3, (u8)(addr & 0xFF)); +} + +static void upd61151_set_data_size(struct v4l2_subdev *sd, u32 dsize) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + + write_reg(spi, UPD61151_DATA_COUNTER1, (u8)((dsize >> 16) & 0xFF)); + write_reg(spi, UPD61151_DATA_COUNTER2, (u8)((dsize >> 8) & 0xFF)); + write_reg(spi, UPD61151_DATA_COUNTER3, (u8)(dsize & 0xFF)); +} + +static u8 upd61151_clear_transfer_irq(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u8 rbyte = 0x00; + + read_reg(spi, UPD61151_TRANSFER_IRQ, &rbyte); + + d2printk_core(KERN_DEBUG "%s: Transfer IRQ status 0x%x\n", spi->modalias, rbyte); + + if (rbyte) + write_reg(spi, UPD61151_IRQ, rbyte); + + return rbyte; +} + +static void upd61151_handle_transfer_err(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u8 rbyte; +printk("upd61151_handle_transfer_err\n"); + /* Set data transfer count size = 1 */ + upd61151_set_data_size(sd, 0x01); + + /* Set transfer mode SDRAM -> Host */ + write_reg(spi, UPD61151_TRANSFER_MODE, 0x01); + + /* Read one byte from SDRAM */ + read_reg(spi, UPD61151_TRANSFER_DATA, &rbyte); + + /* Release transfer mode */ + write_reg(spi, UPD61151_TRANSFER_MODE, 0x00); + + /* Clear IRQ */ + upd61151_clear_transfer_irq(sd); + + /* Set destination address to 0x000000 */ + upd61151_set_dest_addr(sd, 0x000000); + + /* Set data transfer count size = 3 */ + upd61151_set_data_size(sd, 0x03); + + /* Set transfer mode SDRAM -> Host */ + write_reg(spi, UPD61151_TRANSFER_MODE, 0x01); + + /* Clear IRQ */ + upd61151_clear_transfer_irq(sd); + + /* Read 3 byte from SDRAM */ + read_reg(spi, UPD61151_TRANSFER_DATA, &rbyte); + read_reg(spi, UPD61151_TRANSFER_DATA, &rbyte); + read_reg(spi, UPD61151_TRANSFER_DATA, &rbyte); + + /* Clear IRQ */ + upd61151_clear_transfer_irq(sd); + + /* Set transfer mode SDRAM -> Host */ + write_reg(spi, UPD61151_TRANSFER_MODE, 0x00); + + /* Clear IRQ */ + upd61151_clear_transfer_irq(sd); +} + +static int upd61151_wait_transfer_irq(struct v4l2_subdev *sd) +{ + u8 i, rstatus; + + rstatus = 0; + /* Wait transfer interrupt */ + for (i=0; i<5; i++) + { + rstatus = upd61151_clear_transfer_irq(sd); + if (rstatus) + break; + msleep(1); + } + + if (!rstatus) + return STATUS_DEVICE_NOT_READY; + + if (rstatus & 0x04) + { + /* Data transfer error */ + upd61151_handle_transfer_err(sd); + return STATUS_DEVICE_DATA_ERROR; + } + + return RESULT_SUCCESS; +} + +static u8 upd61151_clear_info_irq(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u8 rbyte = 0x00; + + read_reg(spi, UPD61151_IRQ, &rbyte); + + d2printk_core(KERN_DEBUG "%s: IRQ status 0x%x\n", spi->modalias, rbyte); + + if (rbyte) + write_reg(spi, UPD61151_IRQ, rbyte); + + return rbyte; +} + +static u8 upd61151_clear_error_irq(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u8 rbyte = 0x00; + + read_reg(spi, UPD61151_ERROR_IRQ, &rbyte); + + d2printk_core(KERN_DEBUG "%s: IRQ error status 0x%x\n", spi->modalias, rbyte); + + if (rbyte) + write_reg(spi, UPD61151_ERROR_IRQ, rbyte); + + return rbyte; +} + +static u8 upd61151_clear_except_irq(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u8 rbyte = 0x00; + + read_reg(spi, UPD61151_EXCEPT_IRQ, &rbyte); + + d2printk_core(KERN_DEBUG "%s: IRQ exception status 0x%x\n", spi->modalias, rbyte); + + if (rbyte) + write_reg(spi, UPD61151_EXCEPT_IRQ, rbyte); + + return rbyte; +} + +static u8 upd61151_get_state(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u8 rbyte = 0x00; + + read_reg(spi, UPD61151_STATUS, &rbyte); + + d2printk_core(KERN_DEBUG "%s: MPEG2 core status %d\n", spi->modalias, rbyte & 0x07); + + return rbyte & 0x07; +} + +static int upd61151_set_state(struct v4l2_subdev *sd, enum upd61151_config nstate) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u8 enstate, k, get_error; + enum upd61151_config wait_state; +printk("upd61151_set_state\n"); + + enstate = (u8)(nstate) | (u8)(UPD61151_COMMAND_CONFIG); + + /* Clear IRQ */ + upd61151_clear_error_irq(sd); + + /* Set state */ + write_reg(spi, UPD61151_COMMAND, enstate); + + /* Wait max 100ms */ + for (k = 0; k < 200; k++) + { + wait_state = upd61151_get_state(sd); + if (wait_state == UPD61151_COMMAND_CONFIG) + { + /* Clear IRQ flags */ + upd61151_clear_info_irq(sd); + + d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), SUCCESS! Delay(%d ms)\n", spi->modalias, nstate, k << 1); + + return RESULT_SUCCESS; + } + + /* Check error interrupt */ + get_error = upd61151_clear_error_irq(sd); + if (get_error & 0x01) + { + /* Invalid command found */ + d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! Invalid Command (IC)!!!\n", spi->modalias, nstate); + break; + } + + if (get_error & 0x02) + { + /* Invalid parameter found */ + d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! Invalid Parameter (IP)!!!\n", spi->modalias, nstate); + break; + } + + if (get_error & 0x04) + { + /* Invalid audio firmware download IADL */ + d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! Invalid Audio Firmware Download (IADL)!!!\n", spi->modalias, nstate); + break; + } + + if (get_error & 0x08) + { + /* Invalid system bitrate */ + d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! Invalid System Bit Rate (ISBR)!!!\n", spi->modalias, nstate); + break; + } + + mdelay(2); + } + + if (k >= 100) + { + d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! TIMEOUT(%d ms)\n", spi->modalias, nstate, k << 1); + } + + return STATUS_DEVICE_NOT_READY; +} + +static int upd61151_load_base_firmware(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u32 size; + const struct firmware *fw; + int ret = RESULT_SUCCESS; + +printk("DEBUG: upd61151_load_base_firmware\n"); + + size = UPD61151_DEFAULT_PS_FIRMWARE_SIZE / 4; + + /* request the firmware, this will block and timeout */ + printk(KERN_INFO "%s: waiting for base firmware upload (%s)...\n", + spi->modalias, UPD61151_DEFAULT_PS_FIRMWARE); + + ret = request_firmware(&fw, UPD61151_DEFAULT_PS_FIRMWARE, + spi->dev.parent); + if (ret) + { + printk(KERN_ERR "%s: Upload failed. (file not found?)\n",spi->modalias); + ret = STATUS_INVALID_PARAMETER; + goto out; + } + else + printk(KERN_DEBUG "%s: firmware read %Zu bytes.\n", spi->modalias, + fw->size); + + if (fw->size != UPD61151_DEFAULT_PS_FIRMWARE_SIZE) + { + printk(KERN_ERR "%s: firmware incorrect size\n", spi->modalias); + ret = STATUS_INVALID_PARAMETER; + goto out; + } + printk(KERN_INFO "%s: base firmware uploading...\n", spi->modalias); + + upd61151_clear_transfer_irq(sd); + + /* CPU reset ON */ + write_reg(spi, UPD61151_SOFTWARE_RST, 0x02); + + /* Set destination address to 0x000000 */ + upd61151_set_dest_addr(sd, 0x000000); + + /* Set transfer data count to firmware size / 4 */ + upd61151_set_data_size(sd, size); + + /* Set transfer mode to Host -> iRAM */ + write_reg(spi, UPD61151_TRANSFER_MODE, 0x80); +printk("fw upload start\n"); + write_fw(spi, UPD61151_TRANSFER_DATA, fw); +printk("fw upload stop\n"); + + ret = upd61151_wait_transfer_irq(sd); + if (ret == RESULT_SUCCESS) + { + /* Release transfer mode */ + write_reg(spi, UPD61151_TRANSFER_MODE, 0x00); + printk(KERN_INFO "%s: base firmware upload complete...\n", spi->modalias); + } + else + printk(KERN_INFO "%s: base firmware upload FAIL...\n", spi->modalias); + +out: + /* CPU reset OFF */ + write_reg(spi, UPD61151_SOFTWARE_RST, 0x00); + release_firmware(fw); + return ret; +} + +static int upd61151_load_audio_firmware(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + const struct firmware *fw; + u32 addr, i; + int ret = RESULT_SUCCESS; + +printk("DEBUG: upd61151_load_audio_firmware\n"); + + /* request the firmware, this will block and timeout */ + printk(KERN_INFO "%s: waiting for audio firmware upload (%s)...\n", + spi->modalias, UPD61151_DEFAULT_AUDIO_FIRMWARE); + + ret = request_firmware(&fw, UPD61151_DEFAULT_AUDIO_FIRMWARE, + spi->dev.parent); + if (ret) + { + printk(KERN_ERR "%s: Upload failed. (file not found?)\n",spi->modalias); + ret = STATUS_INVALID_PARAMETER; + goto out; + } + else + printk(KERN_DEBUG "%s: firmware read %Zu bytes.\n", spi->modalias, + fw->size); + + if (fw->size != UPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE) + { + printk(KERN_ERR "%s: firmware incorrect size\n", spi->modalias); + ret = STATUS_INVALID_PARAMETER; + goto out; + } + printk(KERN_INFO "%s: audio firmware uploading...\n", spi->modalias); + + addr = 0x308F00; + addr >>= 5; + + upd61151_clear_transfer_irq(sd); + + /* Set destination address */ + upd61151_set_dest_addr(sd, addr); + + /* Set transfer data count to firmware size */ + upd61151_set_data_size(sd, UPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE); + + /* Set transfer mode to Host -> SDRAM */ + write_reg(spi, UPD61151_TRANSFER_MODE, 0x02); + +printk("fw upload start\n"); + + for (i = 0; i < UPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE; i++) + { + write_reg(spi, UPD61151_TRANSFER_DATA, *(fw->data+i)); + + /* Check Transfer interrupt each 128 bytes */ + if ( ((i+1) % 128) ==0 ) + { + ret = upd61151_wait_transfer_irq(sd); + if (ret != RESULT_SUCCESS) + break; + } + } + +printk("fw upload stop\n"); + + if (ret == RESULT_SUCCESS) + { + /* Release transfer mode */ + write_reg(spi, UPD61151_TRANSFER_MODE, 0x00); + printk(KERN_INFO "%s: audio firmware upload complete...\n", spi->modalias); + } + else + printk(KERN_INFO "%s: audio firmware upload FAIL...\n", spi->modalias); + +out: + release_firmware(fw); + return ret; +} + +static int upd61151_chip_command(struct v4l2_subdev *sd, enum upd61151_command command) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + u8 cycles, wait, i, irqerr; + enum upd61151_command want_state; + +printk("DEBUG uPD61151: upd61151_chip_command\n"); + + /* calculate delay */ + cycles = 100; + wait = 10; + + switch (command) + { + case UPD61151_COMMAND_STANDBY_STOP: + case UPD61151_COMMAND_PAUSE: + break; + + case UPD61151_COMMAND_START_RESTART: + cycles = 100; + wait = 2; + break; + + default: + return STATUS_INVALID_PARAMETER; + } + + /* Clear IRQ */ + upd61151_clear_error_irq(sd); + + write_reg(spi, UPD61151_COMMAND, command); + + for (i=0; i < cycles; i++) + { + /* Check state */ + want_state = upd61151_get_state(sd); + if (want_state == command) + { + upd61151_clear_info_irq(sd); + d2printk_core(KERN_DEBUG "%s: SetState(%d) SUCCESS!!! Delay [%d ms].\n", spi->modalias, want_state, i*wait); + return RESULT_SUCCESS; + } + + /* Check error interrupt */ + irqerr = upd61151_clear_error_irq(sd); + + if (irqerr & 0x01) + { + d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! Invalid Command (IC).\n", spi->modalias, command); + break; + } + + if (irqerr & 0x02) + { + d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! Invalid Parameter (IP).\n", spi->modalias, command); + break; + } + + if (irqerr & 0x04) + { + d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! Invalid Audio Firmware Download (IADL).\n", spi->modalias, command); + break; + } + + if (irqerr & 0x08) + { + d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! Invalid System Bit Rate (ISBR).\n", spi->modalias, command); + break; + } + + msleep(wait); + } + + if (i >= cycles) + { + d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! TIMEOUT [%d ms].\n", spi->modalias, command, cycles*wait); + } + + return STATUS_DEVICE_NOT_READY; +} + +static int upd61151_setup_video_frontend(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + u8 dbyte; + +printk("upd61151_setup_video_frontend\n"); + + dbyte = 0x00; + /* Update FIDT */ + if (h->standard & V4L2_STD_625_50) + dbyte |= 0x10; +printk(" 0x%x ",dbyte); + dbyte |= h->video_format; +printk(" 0x%x \n",dbyte); + write_reg(spi, UPD61151_VIDEO_ATTRIBUTE, dbyte); + + /* SAV/EAV (ITU-656), FID not inverted */ + write_reg(spi, UPD61151_VIDEO_SYNC, 0x80); + + /* Set H offset */ + write_reg(spi, UPD61151_VIDEO_HOFFSET, 0x00); + + /* Set V offset */ + if (h->standard & V4L2_STD_625_50) + dbyte = 0x01; + else + dbyte = 0x03; + write_reg(spi, UPD61151_VIDEO_VOFFSET, dbyte); + + /* Setup VBI */ + /* SLCEN = 0, VBIOFFV = 4, VBIOFFH = 8*/ + write_reg(spi, UPD61151_VBI_ADJ1, 0x48); + + return 0; +} + +static int upd61151_setup_audio_frontend(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + struct upd61151_mpeg_params *params = &h->params; + u8 dbyte; + +printk("upd61151_setup_audio_frontend\n"); + dbyte = 0x00; + /* Setup AUDIO attribute 1 */ + switch (params->au_sampling) + { + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + dbyte |= 0x20; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: + dbyte |= 0x10; + break; + default: + break; + } + + switch (params->au_l2_bitrate) + { + case V4L2_MPEG_AUDIO_L2_BITRATE_128K : + dbyte |= 0x05; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_160K : + dbyte |= 0x06; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_192K : + dbyte |= 0x07; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_224K : + dbyte |= 0x08; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_320K : + dbyte |= 0x0A; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_384K : + dbyte |= 0x0B; + break; + default: + dbyte |= 0x09; + break; + } + + write_reg(spi, UPD61151_AUDIO_ATTRIBUTE2, dbyte); + + /* PLLs = internal, AMCLK = 384fs, AQ = 16bit & 64bck, APCMI = I2S, APCMO = OFF*/ + write_reg(spi, UPD61151_AUDIO_INTERFACE, 0x5B); + return 0; +} + +static void upd61151_prepare_bitrates(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + u32 mindelta, minvbr; +printk("upd61151_prepare_bitrates\n"); + + if (h->params.vi_bitrate_peak > 15000) + h->params.vi_bitrate_peak = 15000; + + + if (h->params.vi_bitrate_mode) + { + if (h->params.vi_bitrate_peak < 1200) + h->params.vi_bitrate_peak = 1200; + + h->params.vi_bitrate = 0; + minvbr = 1000; + } + else + { + if (h->params.vi_bitrate_peak < 1500) + h->params.vi_bitrate_peak = 1500; + + if (h->params.vi_bitrate < 1200) + h->params.vi_bitrate = 1200; + + if (h->params.vi_bitrate <= 3000) + /* Min = Average - 20% */ + mindelta = (h->params.vi_bitrate * 2) / 100; + else + /* Min = Average - 30% */ + mindelta = (h->params.vi_bitrate * 3) / 100; + + minvbr = h->params.vi_bitrate - mindelta; + + if (minvbr < 1000) + minvbr = 1000; + } + + /* Set Video bitrates */ + write_reg(spi, UPD61151_VMAXRATE, (u8)(h->params.vi_bitrate_peak / 100)); + write_reg(spi, UPD61151_VAVRATE, (u8)(h->params.vi_bitrate / 100)); + write_reg(spi, UPD61151_VMINRATE, (u8)(minvbr / 100)); + + /* Set VMAXDEBT - 252Mbps */ + write_reg(spi, UPD61151_VMAXDEBT, 0xFC); + +} + +static int upd61151_config_encoder(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + u8 video_attrib1, video_attrib2; + u8 audio_attrib1, audio_attrib2; + u8 mux, mute, aspr; + +printk("upd61151_config_encoder\n"); + + video_attrib1 = 0x00; + /* Set Video resolution*/ + video_attrib1 |= h->video_format; + /* Set GOP */ + /* for gop_size = 0, GOP M=3, N=15 */ + /* for gop_size = 1, GOP M=1, N=15 */ + if (!h->params.video_gop_size) + video_attrib1 |= 0x80; + /* Set TV system */ + if (h->standard & V4L2_STD_625_50) + video_attrib1 |= 0x10; +printk("Video attrib1 = 0x%x\n",video_attrib1); + + video_attrib2 = 0x00; + /* Set Rate control */ + if (!h->params.vi_bitrate_mode) + video_attrib2 |= 0x04; + /* Set GOP, Open GOP = 0, Closed GOP = 1 */ + if (h->params.video_gop_closure) + video_attrib2 |= 0x10; + /* Set adaptive M control */ + /* FIXME: hardcoded adaptive M to enabled */ + video_attrib2 |= 0x20; + /* Set DC precision control */ + /* FIXME: hardcoded 9 bit */ + video_attrib2 |= 0x01; + + /* Set Audio mode */ + /* FIXME: hardcoded audio to MPEG layer 2, 2ch stereo */ + audio_attrib1 = 0x41; + + audio_attrib2 = 0x00; + switch (h->params.au_sampling) + { + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + audio_attrib2 |= 0x20; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: + audio_attrib2 |= 0x10; + break; + default: + break; + } + + /* Set audio bitrate */ + switch (h->params.au_l2_bitrate) + { + case V4L2_MPEG_AUDIO_L2_BITRATE_128K : + audio_attrib2 |= 0x05; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_160K : + audio_attrib2 |= 0x06; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_192K : + audio_attrib2 |= 0x07; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_224K : + audio_attrib2 |= 0x08; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_320K : + audio_attrib2 |= 0x0A; + break; + case V4L2_MPEG_AUDIO_L2_BITRATE_384K : + audio_attrib2 |= 0x0B; + break; + default: + audio_attrib2 |= 0x09; + break; + } + + /* Set aspect */ + aspr = 0x00; + if (h->params.vi_aspect == V4L2_MPEG_VIDEO_ASPECT_16x9) + aspr = 0x20; + + /* Enable Audio */ + /* FIXME: hardcoded enable Audio at all time */ + mux = 0x03; + write_reg(spi, UPD61151_MUX_CTRL, mux); + + /* Enable Video or blue screen */ + mute = 0x00; + /* FIXME: hardcoded enable Video at all time */ + write_reg(spi, UPD61151_ENCODING_TYPE, mute); + + /* Prepare bitrates */ + upd61151_prepare_bitrates(sd); + + write_reg(spi, UPD61151_VIDEO_ATTRIBUTE, video_attrib1); + write_reg(spi, UPD61151_VIDEO_MODE, video_attrib2); + write_reg(spi, UPD61151_AUDIO_ATTRIBUTE1, audio_attrib1); + write_reg(spi, UPD61151_AUDIO_ATTRIBUTE2, audio_attrib2); + + /* FIXME: hardcoded value */ + /* Set brightness noise reducer to level 1 */ + /* Set color noise reducer to level 1 */ + write_reg(spi, UPD61151_VIDEO_NOISE, 0x05); + + write_reg(spi, UPD61151_ASPR, aspr); + return 0; +} + +static int upd61151_download_firmware(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + int res_cmd; + +printk("DEBUG: upd61151_download_firmware\n"); + h->enstate = UPD61151_ENCODE_STATE_IDLE; + + upd61151_reset_core(sd); + + udelay(1); + + /* Init SDRAM */ + write_reg(spi, UPD61151_SDRAM_IF_DELAY_ADJ, 0x01); + write_reg(spi, UPD61151_SDRAM_FCLK_SEL, 0xA0); + + udelay(200); + + /* Set SDRAM to STANDBY */ + write_reg(spi, UPD61151_SDRAM_STANDBY, 0x01); + + udelay(10); + + /* Release SDRAM from STANDBY */ + write_reg(spi, UPD61151_SDRAM_STANDBY, 0x00); + + res_cmd = upd61151_load_base_firmware(sd); + if (res_cmd != RESULT_SUCCESS) + return res_cmd; + + res_cmd = upd61151_load_audio_firmware(sd); + if (res_cmd != RESULT_SUCCESS) + return res_cmd; + + /* Clear IRQ flags */ + if ( !(upd61151_clear_info_irq(sd) & 0x10) ) + { + /* INICM not running */ + d1printk_core(KERN_DEBUG "%s: download firmware FAILED. INICM is not run.\n", spi->modalias); + return STATUS_DEVICE_NOT_READY; + } + + /* Set STANDBY state */ + res_cmd = upd61151_chip_command(sd, UPD61151_COMMAND_STANDBY_STOP); + if (res_cmd != RESULT_SUCCESS) + return res_cmd; + + /* Setup video input frontend */ + upd61151_setup_video_frontend(sd); + + /* Setup audio input frontend */ + upd61151_setup_audio_frontend(sd); + + /* Config encoder params */ + upd61151_config_encoder(sd); + + /* Set all config and upload audio firmware */ + res_cmd = upd61151_set_state(sd, UPD61151_CONFIG_ALL); + if (res_cmd != RESULT_SUCCESS) + return res_cmd; + + /* Return to STANDBY state */ + res_cmd = upd61151_chip_command(sd, UPD61151_COMMAND_STANDBY_STOP); + if (res_cmd != RESULT_SUCCESS) + return res_cmd; + + return RESULT_SUCCESS; +} + +static int upd61151_is_need_reload_fw(struct v4l2_subdev *sd) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + + if (upd61151_get_state(sd) == UPD61151_COMMAND_INITIAL) + { + d1printk_core(KERN_DEBUG "%s: need reload firmware\n", spi->modalias); + return 1; + } + + if (upd61151_clear_except_irq(sd) & 0x04) + { + d1printk_core(KERN_DEBUG "%s: mainly buffer of encoder is overflowed\n", spi->modalias); + return 1; + } + + return 0; +} + +/* Prepare audio PLLs */ +static void upd61151_prepare_i2s(struct v4l2_subdev *sd) +{ +printk("DEBUG uPD61151: upd61151_prepare_i2s\n"); +printk("WARNING: The function upd61151_prepare_i2s is EMPTY\n"); +} + +static int upd61151_init(struct v4l2_subdev *sd, u32 leading_null_bytes) +{ + int res; + +printk("DEBUG uPD61151: upd61151_init\n"); + + if (upd61151_is_need_reload_fw(sd)) + { + printk("Start load firmware...\n"); + if (!upd61151_download_firmware(sd)) + printk("Firmware downloaded SUCCESS!!!\n"); + else + printk("Firmware downloaded FAIL!!!\n"); + } + else + printk("Firmware is OK\n"); + + /* Prepare bitrates */ + upd61151_prepare_bitrates(sd); + + /* Prepare audio PLLs */ + upd61151_prepare_i2s(sd); +printk("switch ON TS MGEP2\n"); + /* FIXME: Hardcoded for SAA7134_BOARD_BEHOLD_X7 */ + /* enable TS out via manipulation with GPIO5 */ +// write_reg(spi, UPD61151_GPIO_CTRLS, 0x10); + + res = upd61151_chip_command(sd, UPD61151_COMMAND_START_RESTART); + if (res != RESULT_SUCCESS) + return res; + + return 0; +} + + +static int get_ctrl(struct upd61151_mpeg_params *params, struct v4l2_ext_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_STREAM_TYPE: + ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_PS; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + ctrl->value = params->au_encoding; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + ctrl->value = params->au_l2_bitrate; + break; + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + ctrl->value = params->au_sampling; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + ctrl->value = params->vi_aspect; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + ctrl->value = params->vi_bitrate * 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + ctrl->value = params->vi_bitrate_peak * 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + ctrl->value = params->vi_bitrate_mode; + break; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + ctrl->value = params->video_gop_size; + break; + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + ctrl->value = params->video_gop_closure; + break; + default: + return -EINVAL; + } + return 0; +} + +static int handle_ctrl(struct upd61151_mpeg_params *params, struct v4l2_ext_control *ctrl, int set) +{ + int old = 0, new; + + new = ctrl->value; + switch (ctrl->id) { + case V4L2_CID_MPEG_STREAM_TYPE: + old = V4L2_MPEG_STREAM_TYPE_MPEG2_PS; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + old = params->au_encoding; + if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2) + return -ERANGE; + params->au_encoding = new; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + old = params->au_l2_bitrate; + if (set && new < V4L2_MPEG_AUDIO_L2_BITRATE_128K && + new > V4L2_MPEG_AUDIO_L2_BITRATE_384K) + return -ERANGE; + params->au_l2_bitrate = new; + break; + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + old = params->au_sampling; + if (set && new > V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 && + new < V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100) + return -ERANGE; + params->au_sampling = new; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + old = params->vi_aspect; + if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && + new != V4L2_MPEG_VIDEO_ASPECT_4x3) + return -ERANGE; + if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) + new = V4L2_MPEG_VIDEO_ASPECT_4x3; + params->vi_aspect = new; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + old = params->vi_bitrate * 1000; + new = 1000 * (new / 1000); + if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + return -ERANGE; + if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; + params->vi_bitrate = new / 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + old = params->vi_bitrate_peak * 1000; + new = 1000 * (new / 1000); + if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + return -ERANGE; + if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; + params->vi_bitrate_peak = new / 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + old = params->vi_bitrate_mode; + params->vi_bitrate_mode = new; + break; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + old = params->video_gop_size; + if (set && new != 0 && new != 1) + return -ERANGE; + params->video_gop_size = new; + break; + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + old = params->video_gop_closure; + if (set && new != 0 && new != 1) + return -ERANGE; + params->video_gop_closure = new; + break; + default: + return -EINVAL; + } + ctrl->value = new; + return 0; +} + +static int upd61151_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + struct upd61151_mpeg_params *params = &h->params; + int err; + +printk("DEBUG uPD61151: upd61151_queryctrl\n"); + switch (qctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); + + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_L2_BITRATE_128K, + V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, + V4L2_MPEG_AUDIO_L2_BITRATE_256K); + + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 3, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000); + + case V4L2_CID_MPEG_VIDEO_ENCODING: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2); + + case V4L2_CID_MPEG_VIDEO_ASPECT: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_ASPECT_4x3, + V4L2_MPEG_VIDEO_ASPECT_16x9, 1, + V4L2_MPEG_VIDEO_ASPECT_4x3); + + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); + if (err == 0 && + params->vi_bitrate_mode == + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_STREAM_TYPE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS, 1, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS); + + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); + case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(qctrl, 0, 15000000, 1, 6000000); + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); + + default: + break; + } + return -EINVAL; +} + +static int upd61151_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu) +{ + static const u32 mpeg_audio_sampling[] = { + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, + V4L2_CTRL_MENU_IDS_END + }; + static const u32 mpeg_audio_encoding[] = { + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + V4L2_CTRL_MENU_IDS_END + }; + static u32 mpeg_audio_l2_bitrate[] = { + V4L2_MPEG_AUDIO_L2_BITRATE_128K, + V4L2_MPEG_AUDIO_L2_BITRATE_160K, + V4L2_MPEG_AUDIO_L2_BITRATE_192K, + V4L2_MPEG_AUDIO_L2_BITRATE_224K, + V4L2_MPEG_AUDIO_L2_BITRATE_256K, + V4L2_MPEG_AUDIO_L2_BITRATE_320K, + V4L2_MPEG_AUDIO_L2_BITRATE_384K, + V4L2_CTRL_MENU_IDS_END + }; + struct v4l2_queryctrl qctrl; + int err; +printk("DEBUG uPD61151: upd61151_querymenu\n"); + qctrl.id = qmenu->id; + err = upd61151_queryctrl(sd, &qctrl); + if (err) + return err; + switch (qmenu->id) { + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + return v4l2_ctrl_query_menu_valid_items(qmenu, mpeg_audio_l2_bitrate); + case V4L2_CID_MPEG_AUDIO_ENCODING: + return v4l2_ctrl_query_menu_valid_items(qmenu, mpeg_audio_encoding); + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + return v4l2_ctrl_query_menu_valid_items(qmenu, mpeg_audio_sampling); + } + return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); +} + +static int upd61151_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + struct upd61151_mpeg_params params; + int i; +printk("DEBUG uPD61151: upd61151_do_ext_ctrls\n"); + + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + + params = h->params; + for (i = 0; i < ctrls->count; i++) { + int err = handle_ctrl(¶ms, ctrls->controls + i, set); + + if (err) { + ctrls->error_idx = i; + return err; + } + } + if (set) + h->params = params; + + return 0; +} + +static int upd61151_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) +{ +printk("DEBUG uPD61151: upd61151_s_ext_ctrls\n"); + return upd61151_do_ext_ctrls(sd, ctrls, 1); +} + +static int upd61151_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) +{ +printk("DEBUG uPD61151: upd61151_s_ext_ctrls\n"); + return upd61151_do_ext_ctrls(sd, ctrls, 0); +} + +static int upd61151_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + int i; +printk("DEBUG uPD61151: upd61151_g_ext_ctrls\n"); + + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + + for (i = 0; i < ctrls->count; i++) { + int err = get_ctrl(&h->params, ctrls->controls + i); + + if (err) { + ctrls->error_idx = i; + return err; + } + } + return 0; +} + +static int upd61151_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + + if (h->video_format == UPD61151_VF_UNKNOWN) + h->video_format = UPD61151_VF_D1; + f->fmt.pix.width = + v4l2_format_table[h->video_format].fmt.pix.width; + f->fmt.pix.height = + v4l2_format_table[h->video_format].fmt.pix.height; + +printk("DEBUG uPD61151: upd61151_g_fmt\n"); + return 0; +} + +static int upd61151_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); + +printk("DEBUG uPD61151: upd61151_s_fmt\n"); + + if (f->fmt.pix.width <= 320) + { + if (f->fmt.pix.height <= 288) + { + f->fmt.pix.width = 320; + f->fmt.pix.height = 288; + h->video_format = UPD61151_VF_D10; + return 0; + } + else + { + f->fmt.pix.width = 320; + f->fmt.pix.height = 576; + h->video_format = UPD61151_VF_D9; + return 0; + } + } + + if (f->fmt.pix.width <= 352) + { + if (f->fmt.pix.height <= 288) + { + f->fmt.pix.width = 352; + f->fmt.pix.height = 288; + h->video_format = UPD61151_VF_D4; + return 0; + } + else + { + f->fmt.pix.width = 352; + f->fmt.pix.height = 576; + h->video_format = UPD61151_VF_D3; + return 0; + } + } + + if (f->fmt.pix.width <= 480) + { + f->fmt.pix.width = 480; + f->fmt.pix.height = 576; + h->video_format = UPD61151_VF_D6; + return 0; + } + + if (f->fmt.pix.width <= 544) + { + f->fmt.pix.width = 544; + f->fmt.pix.height = 576; + h->video_format = UPD61151_VF_D5; + return 0; + } + + if (f->fmt.pix.width <= 640) + { + f->fmt.pix.width = 640; + f->fmt.pix.height = 576; + h->video_format = UPD61151_VF_D8; + return 0; + } + + if (f->fmt.pix.width <= 704) + { + f->fmt.pix.width = 704; + f->fmt.pix.height = 576; + h->video_format = UPD61151_VF_D2; + return 0; + } + + f->fmt.pix.width = 720; + f->fmt.pix.height = 576; + h->video_format = UPD61151_VF_D1; + return 0; +} + +static int upd61151_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct spi_device *spi = v4l2_get_subdevdata(sd); + struct upd61151_state *h = spi_get_drvdata(spi); +printk("DEBUG uPD61151: upd61151_s_std\n"); + h->standard = std; + return 0; +} + +static int upd61151_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ +printk("DEBUG uPD61151: upd61151_g_chip_ident\n"); + chip->ident = V4L2_IDENT_UPD61161; + chip->revision = 0; + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops upd61151_core_ops = { + .g_chip_ident = upd61151_g_chip_ident, /* done */ + .init = upd61151_init, + .queryctrl = upd61151_queryctrl, /* done */ + .querymenu = upd61151_querymenu, /* done */ + .g_ext_ctrls = upd61151_g_ext_ctrls, /* done */ + .s_ext_ctrls = upd61151_s_ext_ctrls, /* done */ + .try_ext_ctrls = upd61151_try_ext_ctrls, /* done */ + .s_std = upd61151_s_std, /* done */ +}; + +static const struct v4l2_subdev_video_ops upd61151_video_ops = { +// .s_fmt = upd61151_s_fmt, /* done */ +// .g_fmt = upd61151_g_fmt, /* done */ +}; + +static const struct v4l2_subdev_ops upd61151_ops = { + .core = &upd61151_core_ops, /* done */ + .video = &upd61151_video_ops, /* done */ +}; + +static int __devinit upd61151_probe(struct spi_device *spi) +{ + struct upd61151_state *h = kzalloc(sizeof(*h), GFP_KERNEL); + struct v4l2_subdev *sd; + +printk("upd61151_probe function\n"); + + if (h == NULL) + return -ENOMEM; + sd = &h->sd; + + v4l2_spi_subdev_init(sd, spi, &upd61151_ops); + + spi_set_drvdata(spi, h); +#if 0 + if (upd61151_is_need_reload_fw(sd)) + { + printk("Start load firmware...\n"); + if (!upd61151_download_firmware(sd)) + printk("Firmware downloaded SUCCESS!!!\n"); + else + printk("Firmware downloaded FAIL!!!\n"); + } + else + printk("Firmware is OK\n"); +#endif + h->params = param_defaults; + h->standard = 0; /* Assume 625 input lines */ + return 0; +} + +static int __devexit upd61151_remove(struct spi_device *spi) +{ + struct upd61151_state *h = spi_get_drvdata(spi); +printk("upd61151_remove function\n"); + v4l2_device_unregister_subdev(&h->sd); + kfree(h); + spi_unregister_device(spi); + return 0; +} + +static struct spi_driver upd61151_driver = { + .driver = { + .name = DRVNAME, + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = upd61151_probe, + .remove = __devexit_p(upd61151_remove), +}; + + +static int __init init_upd61151(void) +{ + return spi_register_driver(&upd61151_driver); +} +module_init(init_upd61151); + +static void __exit exit_upd61151(void) +{ + spi_unregister_driver(&upd61151_driver); +} +module_exit(exit_upd61151); diff --git a/include/media/upd61151.h b/include/media/upd61151.h new file mode 100644 index 0000000..49d2a30 --- /dev/null +++ b/include/media/upd61151.h @@ -0,0 +1,125 @@ +/* + upd61151.h - definition for NEC uPD61151 MPEG encoder + + Copyright (C) Beholder Intl. Ltd. Dmitry Belimov + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include + +#define UPD61151_DEFAULT_PS_FIRMWARE "D61151_PS_7133_v22_031031.bin" +#define UPD61151_DEFAULT_PS_FIRMWARE_SIZE 97002 + +#define UPD61151_DEFAULT_AUDIO_FIRMWARE "audrey_MPE_V1r51.bin" +#define UPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE 40064 + +enum mpeg_audio_bitrate { + MPEG_AUDIO_BITRATE_128 = 5, /* 128 kBit/sec */ + MPEG_AUDIO_BITRATE_160 = 6, /* 160 kBit/sec */ + MPEG_AUDIO_BITRATE_192 = 7, /* 192 kBit/sec */ + MPEG_AUDIO_BITRATE_224 = 8, /* 224 kBit/sec */ + MPEG_AUDIO_BITRATE_256 = 9, /* 256 kBit/sec */ + MPEG_AUDIO_BITRATE_320 = 10, /* 320 kBit/sec */ + MPEG_AUDIO_BITRATE_384 = 11, /* 384 kBit/sec */ + + MPEG_AUDIO_BITRATE_MAX +}; + +enum mpeg_video_format { + MPEG_VIDEO_FORMAT_D1 = 0, /* 720x480/720x576 */ + MPEG_VIDEO_FORMAT_D2 = 1, /* 704x480/704x576 */ + MPEG_VIDEO_FORMAT_D3 = 2, /* 352x480/352x576 */ + MPEG_VIDEO_FORMAT_D4 = 3, /* 352x240/352x288 */ + MPEG_VIDEO_FORMAT_D5 = 4, /* 544x480/544x576 */ + MPEG_VIDEO_FORMAT_D6 = 5, /* 480x480/480x576 */ + MPEG_VIDEO_FORMAT_D7 = 6, /* 352x240/352x288 */ + MPEG_VIDEO_FORMAT_D8 = 8, /* 640x480/640x576 */ + MPEG_VIDEO_FORMAT_D9 = 9, /* 320x480/320x576 */ + MPEG_VIDEO_FORMAT_D10 = 10, /* 320x240/320x288 */ + + MPEG_VIDEO_FORMAT_MAX +}; + +#define MPEG_VIDEO_TARGET_BITRATE_MAX 15000 +#define MPEG_VIDEO_MAX_BITRATE_MAX 15000 +#define MPEG_TOTAL_BITRATE_MAX 15000 +#define MPEG_PID_MAX ((1 << 14) - 1) + +enum upd61151_command { + UPD61151_COMMAND_INITIAL = 0x00, + UPD61151_COMMAND_STANDBY_STOP = 0x01, + UPD61151_COMMAND_CONFIG = 0x02, + UPD61151_COMMAND_START_RESTART = 0x03, + UPD61151_COMMAND_PAUSE = 0x04, + UPD61151_COMMAND_CHANGE = 0x05, +}; + +enum upd61151_encode_state { + UPD61151_ENCODE_STATE_IDLE = 0, + UPD61151_ENCODE_STATE_ENCODE = 1, + UPD61151_ENCODE_STATE_PAUSE = 2, +}; + +enum upd61151_config { + UPD61151_CONFIG_ALL = 0x00, + UPD61151_CONFIG_AUDIO_FW = 0x10, + UPD61151_CONFIG_VIDEO_INPUT = 0x20, + UPD61151_CONFIG_VBI_INPUT = 0x30, + UPD61151_CONFIG_AUDIO_INPUT = 0x40, +}; + +#define UPD61151_COMMAND 0x00 +#define UPD61151_STATUS 0x04 +#define UPD61151_ENCODING_TYPE 0x08 +#define UPD61151_MUX_CTRL 0x0C +#define UPD61151_VMAXRATE 0x10 +#define UPD61151_VAVRATE 0x14 +#define UPD61151_VIDEO_ATTRIBUTE 0x1C +#define UPD61151_VIDEO_MODE 0x20 +#define UPD61151_VIDEO_NOISE 0x24 +#define UPD61151_AUDIO_ATTRIBUTE1 0x28 +#define UPD61151_AUDIO_ATTRIBUTE2 0x2C +#define UPD61151_VMINRATE 0x30 +#define UPD61151_VMAXDEBT 0x34 +#define UPD61151_ASPR 0x38 +#define UPD61151_VIDEO_SYNC 0x54 +#define UPD61151_VIDEO_HOFFSET 0x58 +#define UPD61151_VIDEO_VOFFSET 0x5C +#define UPD61151_AUDIO_INTERFACE 0x60 +#define UPD61151_VBI_ADJ1 0x74 +#define UPD61151_VBI_ADJ2 0x78 +#define UPD61151_TRANSFER_MODE 0x80 +#define UPD61151_TRANSFER_ADDR1 0x90 +#define UPD61151_TRANSFER_ADDR2 0x94 +#define UPD61151_TRANSFER_ADDR3 0x98 +#define UPD61151_DATA_COUNTER1 0x9C +#define UPD61151_DATA_COUNTER2 0xA0 +#define UPD61151_DATA_COUNTER3 0xA4 +#define UPD61151_TRANSFER_IRQ 0xC0 +#define UPD61151_IRQ 0xC4 +#define UPD61151_ERROR_IRQ 0xCC +#define UPD61151_EXCEPT_IRQ 0xD0 +#define UPD61151_SDRAM_IF_DELAY_ADJ 0xDC +#define UPD61151_SDRAM_FCLK_SEL 0xE0 +#define UPD61151_SDRAM_STANDBY 0xE8 +#define UPD61151_GPIO_CTRLS 0xF0 +#define UPD61151_SOFTWARE_RST 0xF8 +#define UPD61151_TRANSFER_DATA 0xFC + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */