mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
Merge branch 'patchwork' into v4l_for_linus
* patchwork: (544 commits) [media] ir-hix5hd2: fix build on c6x arch [media] pt3: fix DTV FE I2C driver load error paths Revert "[media] media: em28xx - remove reset_resume interface" [media] exynos4-is: fix some warnings when compiling on arm64 [media] usb drivers: use %zu instead of %zd [media] pci drivers: use %zu instead of %zd [media] dvb-frontends: use %zu instead of %zd [media] s5p-mfc: Fix several printk warnings [media] s5p_mfc_opr: Fix warnings [media] ti-vpe: Fix typecast [media] s3c-camif: fix dma_addr_t printks [media] s5p_mfc_opr_v6: get rid of warnings when compiled with 64 bits [media] s5p_mfc_opr_v5: Fix lots of warnings on x86_64 [media] em28xx: Fix identation [media] drxd: remove a dead code [media] saa7146: remove return after BUG() [media] cx88: remove return after BUG() [media] cx88: fix cards table CodingStyle [media] radio-sf16fmr2: declare some structs as static [media] radio-sf16fmi: declare pnp_attached as static ... Conflicts: Documentation/DocBook/media/v4l/compat.xml
This commit is contained in:
commit
a66d05d504
@ -2566,6 +2566,12 @@ fields changed from _s32 to _u32.
|
||||
<para>Added compound control types and &VIDIOC-QUERY-EXT-CTRL;.
|
||||
</para>
|
||||
</listitem>
|
||||
<title>V4L2 in Linux 3.18</title>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>Added <constant>V4L2_CID_PAN_SPEED</constant> and
|
||||
<constant>V4L2_CID_TILT_SPEED</constant> camera controls.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
|
||||
|
@ -3965,6 +3965,27 @@ by exposure, white balance or focus controls.</entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_PAN_SPEED</constant> </entry>
|
||||
<entry>integer</entry>
|
||||
</row><row><entry spanname="descr">This control turns the
|
||||
camera horizontally at the specific speed. The unit is undefined. A
|
||||
positive value moves the camera to the right (clockwise when viewed
|
||||
from above), a negative value to the left. A value of zero stops the motion
|
||||
if one is in progress and has no effect otherwise.</entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_TILT_SPEED</constant> </entry>
|
||||
<entry>integer</entry>
|
||||
</row><row><entry spanname="descr">This control turns the
|
||||
camera vertically at the specified speed. The unit is undefined. A
|
||||
positive value moves the camera up, a negative value down. A value of zero
|
||||
stops the motion if one is in progress and has no effect otherwise.</entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
@ -4790,6 +4811,40 @@ interface and may change in the future.</para>
|
||||
conversion.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_RED</constant></entry>
|
||||
<entry>integer</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry spanname="descr">Test pattern red colour component.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_GREENR</constant></entry>
|
||||
<entry>integer</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry spanname="descr">Test pattern green (next to red)
|
||||
colour component.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_BLUE</constant></entry>
|
||||
<entry>integer</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry spanname="descr">Test pattern blue colour component.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_GREENB</constant></entry>
|
||||
<entry>integer</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry spanname="descr">Test pattern green (next to blue)
|
||||
colour component.
|
||||
</entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
@ -237,9 +237,9 @@ for a pixel lie next to each other in memory.</para>
|
||||
<entry>g<subscript>4</subscript></entry>
|
||||
<entry>g<subscript>3</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-RGB555X">
|
||||
<entry><constant>V4L2_PIX_FMT_RGB555X</constant></entry>
|
||||
<entry>'RGBQ'</entry>
|
||||
<row id="V4L2-PIX-FMT-ARGB555X">
|
||||
<entry><constant>V4L2_PIX_FMT_ARGB555X</constant></entry>
|
||||
<entry>'AR15' | (1 << 31)</entry>
|
||||
<entry></entry>
|
||||
<entry>a</entry>
|
||||
<entry>r<subscript>4</subscript></entry>
|
||||
@ -259,6 +259,28 @@ for a pixel lie next to each other in memory.</para>
|
||||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-XRGB555X">
|
||||
<entry><constant>V4L2_PIX_FMT_XRGB555X</constant></entry>
|
||||
<entry>'XR15' | (1 << 31)</entry>
|
||||
<entry></entry>
|
||||
<entry>-</entry>
|
||||
<entry>r<subscript>4</subscript></entry>
|
||||
<entry>r<subscript>3</subscript></entry>
|
||||
<entry>r<subscript>2</subscript></entry>
|
||||
<entry>r<subscript>1</subscript></entry>
|
||||
<entry>r<subscript>0</subscript></entry>
|
||||
<entry>g<subscript>4</subscript></entry>
|
||||
<entry>g<subscript>3</subscript></entry>
|
||||
<entry></entry>
|
||||
<entry>g<subscript>2</subscript></entry>
|
||||
<entry>g<subscript>1</subscript></entry>
|
||||
<entry>g<subscript>0</subscript></entry>
|
||||
<entry>b<subscript>4</subscript></entry>
|
||||
<entry>b<subscript>3</subscript></entry>
|
||||
<entry>b<subscript>2</subscript></entry>
|
||||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-RGB565X">
|
||||
<entry><constant>V4L2_PIX_FMT_RGB565X</constant></entry>
|
||||
<entry>'RGBR'</entry>
|
||||
@ -464,7 +486,7 @@ for a pixel lie next to each other in memory.</para>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-ARGB32">
|
||||
<entry><constant>V4L2_PIX_FMT_ARGB32</constant></entry>
|
||||
<entry>'AX24'</entry>
|
||||
<entry>'BA24'</entry>
|
||||
<entry></entry>
|
||||
<entry>a<subscript>7</subscript></entry>
|
||||
<entry>a<subscript>6</subscript></entry>
|
||||
@ -800,6 +822,28 @@ image</title>
|
||||
<entry>g<subscript>4</subscript></entry>
|
||||
<entry>g<subscript>3</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-RGB555X">
|
||||
<entry><constant>V4L2_PIX_FMT_RGB555X</constant></entry>
|
||||
<entry>'RGBQ'</entry>
|
||||
<entry></entry>
|
||||
<entry>a</entry>
|
||||
<entry>r<subscript>4</subscript></entry>
|
||||
<entry>r<subscript>3</subscript></entry>
|
||||
<entry>r<subscript>2</subscript></entry>
|
||||
<entry>r<subscript>1</subscript></entry>
|
||||
<entry>r<subscript>0</subscript></entry>
|
||||
<entry>g<subscript>4</subscript></entry>
|
||||
<entry>g<subscript>3</subscript></entry>
|
||||
<entry></entry>
|
||||
<entry>g<subscript>2</subscript></entry>
|
||||
<entry>g<subscript>1</subscript></entry>
|
||||
<entry>g<subscript>0</subscript></entry>
|
||||
<entry>b<subscript>4</subscript></entry>
|
||||
<entry>b<subscript>3</subscript></entry>
|
||||
<entry>b<subscript>2</subscript></entry>
|
||||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-BGR32">
|
||||
<entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
|
||||
<entry>'BGR4'</entry>
|
||||
|
@ -76,21 +76,22 @@
|
||||
<entry></entry>
|
||||
<entry>&v4l2-event-vsync;</entry>
|
||||
<entry><structfield>vsync</structfield></entry>
|
||||
<entry>Event data for event V4L2_EVENT_VSYNC.
|
||||
<entry>Event data for event <constant>V4L2_EVENT_VSYNC</constant>.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>&v4l2-event-ctrl;</entry>
|
||||
<entry><structfield>ctrl</structfield></entry>
|
||||
<entry>Event data for event V4L2_EVENT_CTRL.
|
||||
<entry>Event data for event <constant>V4L2_EVENT_CTRL</constant>.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>&v4l2-event-frame-sync;</entry>
|
||||
<entry><structfield>frame_sync</structfield></entry>
|
||||
<entry>Event data for event V4L2_EVENT_FRAME_SYNC.</entry>
|
||||
<entry>Event data for event
|
||||
<constant>V4L2_EVENT_FRAME_SYNC</constant>.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>const struct v4l2_edid *<parameter>argp</parameter></paramdef>
|
||||
<paramdef>struct v4l2_edid *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
@ -124,18 +124,18 @@
|
||||
maximum number of blocks as defined by the standard). When you set the EDID and
|
||||
<structfield>blocks</structfield> is 0, then the EDID is disabled or erased.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u8 *</entry>
|
||||
<entry><structfield>edid</structfield></entry>
|
||||
<entry>Pointer to memory that contains the EDID. The minimum size is
|
||||
<structfield>blocks</structfield> * 128.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[5]</entry>
|
||||
<entry>Reserved for future extensions. Applications and drivers must
|
||||
set the array to zero.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u8 *</entry>
|
||||
<entry><structfield>edid</structfield></entry>
|
||||
<entry>Pointer to memory that contains the EDID. The minimum size is
|
||||
<structfield>blocks</structfield> * 128.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
@ -176,7 +176,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
|
||||
<entry>5</entry>
|
||||
<entry>6</entry>
|
||||
<entry>
|
||||
<para>Triggered whenever the motion detection state for one or more of the regions
|
||||
changes. This event has a &v4l2-event-motion-det; associated with it.</para>
|
||||
|
25
Documentation/devicetree/bindings/media/hix5hd2-ir.txt
Normal file
25
Documentation/devicetree/bindings/media/hix5hd2-ir.txt
Normal file
@ -0,0 +1,25 @@
|
||||
Device-Tree bindings for hix5hd2 ir IP
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain "hisilicon,hix5hd2-ir".
|
||||
- reg: Base physical address of the controller and length of memory
|
||||
mapped region.
|
||||
- interrupts: interrupt-specifier for the sole interrupt generated by
|
||||
the device. The interrupt specifier format depends on the interrupt
|
||||
controller parent.
|
||||
- clocks: clock phandle and specifier pair.
|
||||
- hisilicon,power-syscon: phandle of syscon used to control power.
|
||||
|
||||
Optional properties:
|
||||
- linux,rc-map-name : Remote control map name.
|
||||
|
||||
Example node:
|
||||
|
||||
ir: ir@f8001000 {
|
||||
compatible = "hisilicon,hix5hd2-ir";
|
||||
reg = <0xf8001000 0x1000>;
|
||||
interrupts = <0 47 4>;
|
||||
clocks = <&clock HIX5HD2_FIXED_24M>;
|
||||
hisilicon,power-syscon = <&sysctrl>;
|
||||
linux,rc-map-name = "rc-tivo";
|
||||
};
|
@ -708,23 +708,25 @@ sub drxk_terratec_htc_stick {
|
||||
}
|
||||
|
||||
sub it9135 {
|
||||
my $sourcefile = "dvb-usb-it9135.zip";
|
||||
my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile";
|
||||
my $hash = "1e55f6c8833f1d0ae067c2bb2953e6a9";
|
||||
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0);
|
||||
my $outfile = "dvb-usb-it9135.fw";
|
||||
my $url = "http://www.ite.com.tw/uploads/firmware/v3.25.0.0/";
|
||||
my $file1 = "dvb-usb-it9135-01.zip";
|
||||
my $fwfile1 = "dvb-usb-it9135-01.fw";
|
||||
my $hash1 = "02fcf11174eda84745dae7e61c5ff9ba";
|
||||
my $file2 = "dvb-usb-it9135-02.zip";
|
||||
my $fwfile2 = "dvb-usb-it9135-02.fw";
|
||||
my $hash2 = "d5e1437dc24358578e07999475d4cac9";
|
||||
|
||||
checkstandard();
|
||||
|
||||
wgetfile($sourcefile, $url);
|
||||
unzip($sourcefile, $tmpdir);
|
||||
verify("$tmpdir/$outfile", $hash);
|
||||
extract("$tmpdir/$outfile", 64, 8128, "$fwfile1");
|
||||
extract("$tmpdir/$outfile", 12866, 5817, "$fwfile2");
|
||||
wgetfile($file1, $url . $file1);
|
||||
unzip($file1, "");
|
||||
verify("$fwfile1", $hash1);
|
||||
|
||||
"$fwfile1 $fwfile2"
|
||||
wgetfile($file2, $url . $file2);
|
||||
unzip($file2, "");
|
||||
verify("$fwfile2", $hash2);
|
||||
|
||||
"$file1 $file2"
|
||||
}
|
||||
|
||||
sub tda10071 {
|
||||
|
1111
Documentation/video4linux/vivid.txt
Normal file
1111
Documentation/video4linux/vivid.txt
Normal file
File diff suppressed because it is too large
Load Diff
28
MAINTAINERS
28
MAINTAINERS
@ -4177,6 +4177,16 @@ L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Odd Fixes
|
||||
F: drivers/tty/hvc/
|
||||
|
||||
HACKRF MEDIA DRIVER
|
||||
M: Antti Palosaari <crope@iki.fi>
|
||||
L: linux-media@vger.kernel.org
|
||||
W: http://linuxtv.org/
|
||||
W: http://palosaari.fi/linux/
|
||||
Q: http://patchwork.linuxtv.org/project/linux-media/list/
|
||||
T: git git://linuxtv.org/anttip/media_tree.git
|
||||
S: Maintained
|
||||
F: drivers/media/usb/hackrf/
|
||||
|
||||
HARDWARE MONITORING
|
||||
M: Jean Delvare <jdelvare@suse.de>
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
@ -5070,7 +5080,7 @@ W: http://palosaari.fi/linux/
|
||||
Q: http://patchwork.linuxtv.org/project/linux-media/list/
|
||||
T: git git://linuxtv.org/anttip/media_tree.git
|
||||
S: Maintained
|
||||
F: drivers/media/tuners/tuner_it913x*
|
||||
F: drivers/media/tuners/it913x*
|
||||
|
||||
IVTV VIDEO4LINUX DRIVER
|
||||
M: Andy Walls <awalls@md.metrocast.net>
|
||||
@ -8588,6 +8598,14 @@ F: include/sound/dmaengine_pcm.h
|
||||
F: sound/core/pcm_dmaengine.c
|
||||
F: sound/soc/soc-generic-dmaengine-pcm.c
|
||||
|
||||
SP2 MEDIA DRIVER
|
||||
M: Olli Salonen <olli.salonen@iki.fi>
|
||||
L: linux-media@vger.kernel.org
|
||||
W: http://linuxtv.org/
|
||||
Q: http://patchwork.linuxtv.org/project/linux-media/list/
|
||||
S: Maintained
|
||||
F: drivers/media/dvb-frontends/sp2*
|
||||
|
||||
SPARC + UltraSPARC (sparc/sparc64)
|
||||
M: "David S. Miller" <davem@davemloft.net>
|
||||
L: sparclinux@vger.kernel.org
|
||||
@ -9293,6 +9311,14 @@ T: git git://linuxtv.org/media_tree.git
|
||||
S: Odd fixes
|
||||
F: drivers/media/usb/tm6000/
|
||||
|
||||
TW68 VIDEO4LINUX DRIVER
|
||||
M: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
W: http://linuxtv.org
|
||||
S: Odd Fixes
|
||||
F: drivers/media/pci/tw68/
|
||||
|
||||
TPM DEVICE DRIVER
|
||||
M: Peter Huewe <peterhuewe@gmx.de>
|
||||
M: Ashley Lai <ashley@ashleylai.com>
|
||||
|
@ -4,7 +4,7 @@
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#ifndef __FLEXCOP_H__
|
||||
#define __FLEXCOP_H___
|
||||
#define __FLEXCOP_H__
|
||||
|
||||
#define FC_LOG_PREFIX "b2c2-flexcop"
|
||||
#include "flexcop-common.h"
|
||||
|
@ -311,7 +311,6 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
|
||||
}
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(vdev->lock))
|
||||
@ -399,7 +398,6 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
|
||||
return -EINVAL;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,7 +421,6 @@ static ssize_t fops_write(struct file *file, const char __user *data, size_t cou
|
||||
return -EINVAL;
|
||||
default:
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,12 @@ static struct sms_board sms_boards[] = {
|
||||
.type = SMS_DENVER_2160,
|
||||
.default_mode = DEVICE_MODE_DAB_TDMB,
|
||||
},
|
||||
[SMS1XXX_BOARD_PCTV_77E] = {
|
||||
.name = "Hauppauge microStick 77e",
|
||||
.type = SMS_NOVA_B0,
|
||||
.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVB_NOVA_12MHZ_B0,
|
||||
.default_mode = DEVICE_MODE_DVBT_BDA,
|
||||
},
|
||||
};
|
||||
|
||||
struct sms_board *sms_get_board(unsigned id)
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define SMS1XXX_BOARD_SIANO_RIO 18
|
||||
#define SMS1XXX_BOARD_SIANO_DENVER_1530 19
|
||||
#define SMS1XXX_BOARD_SIANO_DENVER_2160 20
|
||||
#define SMS1XXX_BOARD_PCTV_77E 21
|
||||
|
||||
struct sms_board_gpio_cfg {
|
||||
int lna_vhf_exist;
|
||||
|
@ -2129,8 +2129,6 @@ int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
|
||||
|
||||
static int __init smscore_module_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
INIT_LIST_HEAD(&g_smscore_notifyees);
|
||||
INIT_LIST_HEAD(&g_smscore_devices);
|
||||
kmutex_init(&g_smscore_deviceslock);
|
||||
@ -2138,7 +2136,7 @@ static int __init smscore_module_init(void)
|
||||
INIT_LIST_HEAD(&g_smscore_registry);
|
||||
kmutex_init(&g_smscore_registrylock);
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit smscore_module_exit(void)
|
||||
|
@ -1087,8 +1087,8 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
|
||||
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (!dmxdevfilter)
|
||||
return -EINVAL;
|
||||
if ((!dmxdevfilter) || dmxdevfilter->dev->exit)
|
||||
return POLLERR;
|
||||
|
||||
poll_wait(file, &dmxdevfilter->buffer.queue, wait);
|
||||
|
||||
@ -1181,6 +1181,9 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
|
||||
|
||||
dprintk("function : %s\n", __func__);
|
||||
|
||||
if (dmxdev->exit)
|
||||
return POLLERR;
|
||||
|
||||
poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
||||
|
@ -144,6 +144,7 @@
|
||||
#define USB_PID_ITETECH_IT9135 0x9135
|
||||
#define USB_PID_ITETECH_IT9135_9005 0x9005
|
||||
#define USB_PID_ITETECH_IT9135_9006 0x9006
|
||||
#define USB_PID_ITETECH_IT9303 0x9306
|
||||
#define USB_PID_KWORLD_399U 0xe399
|
||||
#define USB_PID_KWORLD_399U_2 0xe400
|
||||
#define USB_PID_KWORLD_395U 0xe396
|
||||
@ -244,6 +245,7 @@
|
||||
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
|
||||
#define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009
|
||||
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
|
||||
#define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI 0x3012
|
||||
#define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014
|
||||
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
|
||||
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
|
||||
|
@ -1934,15 +1934,13 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int err = 0;
|
||||
|
||||
struct dtv_properties *tvps = NULL;
|
||||
struct dtv_properties *tvps = parg;
|
||||
struct dtv_property *tvp = NULL;
|
||||
int i;
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
if(cmd == FE_SET_PROPERTY) {
|
||||
tvps = (struct dtv_properties __user *)parg;
|
||||
|
||||
if (cmd == FE_SET_PROPERTY) {
|
||||
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
|
||||
dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
|
||||
|
||||
@ -1957,7 +1955,8 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
|
||||
if (copy_from_user(tvp, (void __user *)tvps->props,
|
||||
tvps->num * sizeof(struct dtv_property))) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
@ -1972,10 +1971,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
if (c->state == DTV_TUNE)
|
||||
dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__);
|
||||
|
||||
} else
|
||||
if(cmd == FE_GET_PROPERTY) {
|
||||
tvps = (struct dtv_properties __user *)parg;
|
||||
|
||||
} else if (cmd == FE_GET_PROPERTY) {
|
||||
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
|
||||
dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
|
||||
|
||||
@ -1990,7 +1986,8 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
|
||||
if (copy_from_user(tvp, (void __user *)tvps->props,
|
||||
tvps->num * sizeof(struct dtv_property))) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
@ -2012,7 +2009,8 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
(tvp + i)->result = err;
|
||||
}
|
||||
|
||||
if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
|
||||
if (copy_to_user((void __user *)tvps->props, tvp,
|
||||
tvps->num * sizeof(struct dtv_property))) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
@ -2072,6 +2070,23 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
|
||||
case SYS_DVBC_ANNEX_C:
|
||||
rolloff = 113;
|
||||
break;
|
||||
case SYS_DVBS:
|
||||
case SYS_TURBO:
|
||||
rolloff = 135;
|
||||
break;
|
||||
case SYS_DVBS2:
|
||||
switch (c->rolloff) {
|
||||
case ROLLOFF_20:
|
||||
rolloff = 120;
|
||||
break;
|
||||
case ROLLOFF_25:
|
||||
rolloff = 125;
|
||||
break;
|
||||
default:
|
||||
case ROLLOFF_35:
|
||||
rolloff = 135;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2550,7 +2565,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe)
|
||||
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
|
||||
fe->id);
|
||||
|
||||
if (fe->ops.tuner_ops.sleep)
|
||||
if (fe->ops.tuner_ops.suspend)
|
||||
ret = fe->ops.tuner_ops.suspend(fe);
|
||||
else if (fe->ops.tuner_ops.sleep)
|
||||
ret = fe->ops.tuner_ops.sleep(fe);
|
||||
|
||||
if (fe->ops.sleep)
|
||||
@ -2572,7 +2589,9 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
|
||||
if (fe->ops.init)
|
||||
ret = fe->ops.init(fe);
|
||||
|
||||
if (fe->ops.tuner_ops.init)
|
||||
if (fe->ops.tuner_ops.resume)
|
||||
ret = fe->ops.tuner_ops.resume(fe);
|
||||
else if (fe->ops.tuner_ops.init)
|
||||
ret = fe->ops.tuner_ops.init(fe);
|
||||
|
||||
fe->exit = DVB_FE_NO_EXIT;
|
||||
|
@ -201,6 +201,8 @@ struct dvb_tuner_ops {
|
||||
int (*release)(struct dvb_frontend *fe);
|
||||
int (*init)(struct dvb_frontend *fe);
|
||||
int (*sleep)(struct dvb_frontend *fe);
|
||||
int (*suspend)(struct dvb_frontend *fe);
|
||||
int (*resume)(struct dvb_frontend *fe);
|
||||
|
||||
/** This is for simple PLLs - set all parameters in one go. */
|
||||
int (*set_params)(struct dvb_frontend *fe);
|
||||
|
@ -166,6 +166,31 @@ ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
|
||||
const u8 __user *buf, size_t len)
|
||||
{
|
||||
int status;
|
||||
size_t todo = len;
|
||||
size_t split;
|
||||
|
||||
split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
|
||||
|
||||
if (split > 0) {
|
||||
status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split);
|
||||
if (status)
|
||||
return len - todo;
|
||||
buf += split;
|
||||
todo -= split;
|
||||
rbuf->pwrite = 0;
|
||||
}
|
||||
status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo);
|
||||
if (status)
|
||||
return len - todo;
|
||||
rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len)
|
||||
{
|
||||
int status;
|
||||
@ -297,3 +322,4 @@ EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_read_user);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_read);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_write);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_write_user);
|
||||
|
@ -133,6 +133,8 @@ extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
|
||||
size_t len);
|
||||
extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
|
||||
const u8 __user *buf, size_t len);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -471,6 +471,11 @@ config DVB_SI2168
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_AS102_FE
|
||||
tristate
|
||||
depends on DVB_CORE
|
||||
default DVB_AS102
|
||||
|
||||
comment "DVB-C (cable) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
@ -643,6 +648,14 @@ config DVB_MB86A20S
|
||||
A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TC90522
|
||||
tristate "Toshiba TC90522"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A Toshiba TC90522 2xISDB-T + 2xISDB-S demodulator.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "Digital terrestrial only tuners/PLL"
|
||||
depends on DVB_CORE
|
||||
|
||||
@ -720,6 +733,13 @@ config DVB_A8293
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
|
||||
config DVB_SP2
|
||||
tristate "CIMaX SP2"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
CIMaX SP2/SP2HF Common Interface module.
|
||||
|
||||
config DVB_LGS8GL5
|
||||
tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
|
||||
depends on DVB_CORE && I2C
|
||||
|
@ -107,10 +107,12 @@ obj-$(CONFIG_DVB_DRXK) += drxk.o
|
||||
obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
|
||||
obj-$(CONFIG_DVB_SI2165) += si2165.o
|
||||
obj-$(CONFIG_DVB_A8293) += a8293.o
|
||||
obj-$(CONFIG_DVB_SP2) += sp2.o
|
||||
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
|
||||
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
|
||||
obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
|
||||
obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
|
||||
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
|
||||
obj-$(CONFIG_DVB_AF9033) += af9033.o
|
||||
|
||||
obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o
|
||||
obj-$(CONFIG_DVB_TC90522) += tc90522.o
|
||||
|
@ -683,7 +683,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
||||
|
||||
switch (c->transmission_mode) {
|
||||
case TRANSMISSION_MODE_AUTO:
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
break;
|
||||
case TRANSMISSION_MODE_2K:
|
||||
break;
|
||||
@ -693,12 +693,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
||||
default:
|
||||
dev_dbg(&state->i2c->dev, "%s: invalid transmission_mode\n",
|
||||
__func__);
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
}
|
||||
|
||||
switch (c->guard_interval) {
|
||||
case GUARD_INTERVAL_AUTO:
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
break;
|
||||
case GUARD_INTERVAL_1_32:
|
||||
break;
|
||||
@ -714,12 +714,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
||||
default:
|
||||
dev_dbg(&state->i2c->dev, "%s: invalid guard_interval\n",
|
||||
__func__);
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
}
|
||||
|
||||
switch (c->hierarchy) {
|
||||
case HIERARCHY_AUTO:
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
break;
|
||||
case HIERARCHY_NONE:
|
||||
break;
|
||||
@ -734,12 +734,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__);
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
}
|
||||
|
||||
switch (c->modulation) {
|
||||
case QAM_AUTO:
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
break;
|
||||
case QPSK:
|
||||
break;
|
||||
@ -751,7 +751,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&state->i2c->dev, "%s: invalid modulation\n", __func__);
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
}
|
||||
|
||||
/* Use HP. How and which case we can switch to LP? */
|
||||
@ -759,7 +759,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
||||
|
||||
switch (c->code_rate_HP) {
|
||||
case FEC_AUTO:
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
break;
|
||||
case FEC_1_2:
|
||||
break;
|
||||
@ -778,12 +778,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
||||
default:
|
||||
dev_dbg(&state->i2c->dev, "%s: invalid code_rate_HP\n",
|
||||
__func__);
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
}
|
||||
|
||||
switch (c->code_rate_LP) {
|
||||
case FEC_AUTO:
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
break;
|
||||
case FEC_1_2:
|
||||
break;
|
||||
@ -804,7 +804,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
||||
default:
|
||||
dev_dbg(&state->i2c->dev, "%s: invalid code_rate_LP\n",
|
||||
__func__);
|
||||
auto_mode = 1;
|
||||
auto_mode = true;
|
||||
}
|
||||
|
||||
switch (c->bandwidth_hz) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,12 +24,11 @@
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
|
||||
/*
|
||||
* I2C address (TODO: are these in 8-bit format?)
|
||||
* 0x38, 0x3a, 0x3c, 0x3e
|
||||
*/
|
||||
struct af9033_config {
|
||||
/*
|
||||
* I2C address
|
||||
*/
|
||||
u8 i2c_addr;
|
||||
|
||||
/*
|
||||
* clock Hz
|
||||
* 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000,
|
||||
@ -75,8 +74,23 @@ struct af9033_config {
|
||||
* input spectrum inversion
|
||||
*/
|
||||
bool spec_inv;
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
bool dyn0_clk;
|
||||
|
||||
/*
|
||||
* PID filter ops
|
||||
*/
|
||||
struct af9033_ops *ops;
|
||||
|
||||
/*
|
||||
* frontend
|
||||
* returned by that driver
|
||||
*/
|
||||
struct dvb_frontend **fe;
|
||||
};
|
||||
|
||||
struct af9033_ops {
|
||||
int (*pid_filter_ctrl)(struct dvb_frontend *fe, int onoff);
|
||||
@ -84,36 +98,4 @@ struct af9033_ops {
|
||||
int onoff);
|
||||
};
|
||||
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_AF9033)
|
||||
extern
|
||||
struct dvb_frontend *af9033_attach(const struct af9033_config *config,
|
||||
struct i2c_adapter *i2c,
|
||||
struct af9033_ops *ops);
|
||||
|
||||
#else
|
||||
static inline
|
||||
struct dvb_frontend *af9033_attach(const struct af9033_config *config,
|
||||
struct i2c_adapter *i2c,
|
||||
struct af9033_ops *ops)
|
||||
{
|
||||
pr_warn("%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
pr_warn("%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid,
|
||||
int onoff)
|
||||
{
|
||||
pr_warn("%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* AF9033_H */
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "af9033.h"
|
||||
#include <linux/math64.h>
|
||||
|
||||
struct reg_val {
|
||||
u32 reg;
|
||||
|
480
drivers/media/dvb-frontends/as102_fe.c
Normal file
480
drivers/media/dvb-frontends/as102_fe.c
Normal file
@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Abilis Systems Single DVB-T Receiver
|
||||
* Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
|
||||
* Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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.
|
||||
*/
|
||||
|
||||
#include <dvb_frontend.h>
|
||||
|
||||
#include "as102_fe.h"
|
||||
|
||||
struct as102_state {
|
||||
struct dvb_frontend frontend;
|
||||
struct as10x_demod_stats demod_stats;
|
||||
|
||||
const struct as102_fe_ops *ops;
|
||||
void *priv;
|
||||
uint8_t elna_cfg;
|
||||
|
||||
/* signal strength */
|
||||
uint16_t signal_strength;
|
||||
/* bit error rate */
|
||||
uint32_t ber;
|
||||
};
|
||||
|
||||
static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
switch (arg) {
|
||||
case FEC_1_2:
|
||||
c = CODE_RATE_1_2;
|
||||
break;
|
||||
case FEC_2_3:
|
||||
c = CODE_RATE_2_3;
|
||||
break;
|
||||
case FEC_3_4:
|
||||
c = CODE_RATE_3_4;
|
||||
break;
|
||||
case FEC_5_6:
|
||||
c = CODE_RATE_5_6;
|
||||
break;
|
||||
case FEC_7_8:
|
||||
c = CODE_RATE_7_8;
|
||||
break;
|
||||
default:
|
||||
c = CODE_RATE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static int as102_fe_set_frontend(struct dvb_frontend *fe)
|
||||
{
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct as10x_tune_args tune_args = { 0 };
|
||||
|
||||
/* set frequency */
|
||||
tune_args.freq = c->frequency / 1000;
|
||||
|
||||
/* fix interleaving_mode */
|
||||
tune_args.interleaving_mode = INTLV_NATIVE;
|
||||
|
||||
switch (c->bandwidth_hz) {
|
||||
case 8000000:
|
||||
tune_args.bandwidth = BW_8_MHZ;
|
||||
break;
|
||||
case 7000000:
|
||||
tune_args.bandwidth = BW_7_MHZ;
|
||||
break;
|
||||
case 6000000:
|
||||
tune_args.bandwidth = BW_6_MHZ;
|
||||
break;
|
||||
default:
|
||||
tune_args.bandwidth = BW_8_MHZ;
|
||||
}
|
||||
|
||||
switch (c->guard_interval) {
|
||||
case GUARD_INTERVAL_1_32:
|
||||
tune_args.guard_interval = GUARD_INT_1_32;
|
||||
break;
|
||||
case GUARD_INTERVAL_1_16:
|
||||
tune_args.guard_interval = GUARD_INT_1_16;
|
||||
break;
|
||||
case GUARD_INTERVAL_1_8:
|
||||
tune_args.guard_interval = GUARD_INT_1_8;
|
||||
break;
|
||||
case GUARD_INTERVAL_1_4:
|
||||
tune_args.guard_interval = GUARD_INT_1_4;
|
||||
break;
|
||||
case GUARD_INTERVAL_AUTO:
|
||||
default:
|
||||
tune_args.guard_interval = GUARD_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c->modulation) {
|
||||
case QPSK:
|
||||
tune_args.modulation = CONST_QPSK;
|
||||
break;
|
||||
case QAM_16:
|
||||
tune_args.modulation = CONST_QAM16;
|
||||
break;
|
||||
case QAM_64:
|
||||
tune_args.modulation = CONST_QAM64;
|
||||
break;
|
||||
default:
|
||||
tune_args.modulation = CONST_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c->transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K:
|
||||
tune_args.transmission_mode = TRANS_MODE_2K;
|
||||
break;
|
||||
case TRANSMISSION_MODE_8K:
|
||||
tune_args.transmission_mode = TRANS_MODE_8K;
|
||||
break;
|
||||
default:
|
||||
tune_args.transmission_mode = TRANS_MODE_UNKNOWN;
|
||||
}
|
||||
|
||||
switch (c->hierarchy) {
|
||||
case HIERARCHY_NONE:
|
||||
tune_args.hierarchy = HIER_NONE;
|
||||
break;
|
||||
case HIERARCHY_1:
|
||||
tune_args.hierarchy = HIER_ALPHA_1;
|
||||
break;
|
||||
case HIERARCHY_2:
|
||||
tune_args.hierarchy = HIER_ALPHA_2;
|
||||
break;
|
||||
case HIERARCHY_4:
|
||||
tune_args.hierarchy = HIER_ALPHA_4;
|
||||
break;
|
||||
case HIERARCHY_AUTO:
|
||||
tune_args.hierarchy = HIER_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
pr_debug("as102: tuner parameters: freq: %d bw: 0x%02x gi: 0x%02x\n",
|
||||
c->frequency,
|
||||
tune_args.bandwidth,
|
||||
tune_args.guard_interval);
|
||||
|
||||
/*
|
||||
* Detect a hierarchy selection
|
||||
* if HP/LP are both set to FEC_NONE, HP will be selected.
|
||||
*/
|
||||
if ((tune_args.hierarchy != HIER_NONE) &&
|
||||
((c->code_rate_LP == FEC_NONE) ||
|
||||
(c->code_rate_HP == FEC_NONE))) {
|
||||
|
||||
if (c->code_rate_LP == FEC_NONE) {
|
||||
tune_args.hier_select = HIER_HIGH_PRIORITY;
|
||||
tune_args.code_rate =
|
||||
as102_fe_get_code_rate(c->code_rate_HP);
|
||||
}
|
||||
|
||||
if (c->code_rate_HP == FEC_NONE) {
|
||||
tune_args.hier_select = HIER_LOW_PRIORITY;
|
||||
tune_args.code_rate =
|
||||
as102_fe_get_code_rate(c->code_rate_LP);
|
||||
}
|
||||
|
||||
pr_debug("as102: \thierarchy: 0x%02x selected: %s code_rate_%s: 0x%02x\n",
|
||||
tune_args.hierarchy,
|
||||
tune_args.hier_select == HIER_HIGH_PRIORITY ?
|
||||
"HP" : "LP",
|
||||
tune_args.hier_select == HIER_HIGH_PRIORITY ?
|
||||
"HP" : "LP",
|
||||
tune_args.code_rate);
|
||||
} else {
|
||||
tune_args.code_rate =
|
||||
as102_fe_get_code_rate(c->code_rate_HP);
|
||||
}
|
||||
|
||||
/* Set frontend arguments */
|
||||
return state->ops->set_tune(state->priv, &tune_args);
|
||||
}
|
||||
|
||||
static int as102_fe_get_frontend(struct dvb_frontend *fe)
|
||||
{
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret = 0;
|
||||
struct as10x_tps tps = { 0 };
|
||||
|
||||
/* send abilis command: GET_TPS */
|
||||
ret = state->ops->get_tps(state->priv, &tps);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* extract constellation */
|
||||
switch (tps.modulation) {
|
||||
case CONST_QPSK:
|
||||
c->modulation = QPSK;
|
||||
break;
|
||||
case CONST_QAM16:
|
||||
c->modulation = QAM_16;
|
||||
break;
|
||||
case CONST_QAM64:
|
||||
c->modulation = QAM_64;
|
||||
break;
|
||||
}
|
||||
|
||||
/* extract hierarchy */
|
||||
switch (tps.hierarchy) {
|
||||
case HIER_NONE:
|
||||
c->hierarchy = HIERARCHY_NONE;
|
||||
break;
|
||||
case HIER_ALPHA_1:
|
||||
c->hierarchy = HIERARCHY_1;
|
||||
break;
|
||||
case HIER_ALPHA_2:
|
||||
c->hierarchy = HIERARCHY_2;
|
||||
break;
|
||||
case HIER_ALPHA_4:
|
||||
c->hierarchy = HIERARCHY_4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* extract code rate HP */
|
||||
switch (tps.code_rate_HP) {
|
||||
case CODE_RATE_1_2:
|
||||
c->code_rate_HP = FEC_1_2;
|
||||
break;
|
||||
case CODE_RATE_2_3:
|
||||
c->code_rate_HP = FEC_2_3;
|
||||
break;
|
||||
case CODE_RATE_3_4:
|
||||
c->code_rate_HP = FEC_3_4;
|
||||
break;
|
||||
case CODE_RATE_5_6:
|
||||
c->code_rate_HP = FEC_5_6;
|
||||
break;
|
||||
case CODE_RATE_7_8:
|
||||
c->code_rate_HP = FEC_7_8;
|
||||
break;
|
||||
}
|
||||
|
||||
/* extract code rate LP */
|
||||
switch (tps.code_rate_LP) {
|
||||
case CODE_RATE_1_2:
|
||||
c->code_rate_LP = FEC_1_2;
|
||||
break;
|
||||
case CODE_RATE_2_3:
|
||||
c->code_rate_LP = FEC_2_3;
|
||||
break;
|
||||
case CODE_RATE_3_4:
|
||||
c->code_rate_LP = FEC_3_4;
|
||||
break;
|
||||
case CODE_RATE_5_6:
|
||||
c->code_rate_LP = FEC_5_6;
|
||||
break;
|
||||
case CODE_RATE_7_8:
|
||||
c->code_rate_LP = FEC_7_8;
|
||||
break;
|
||||
}
|
||||
|
||||
/* extract guard interval */
|
||||
switch (tps.guard_interval) {
|
||||
case GUARD_INT_1_32:
|
||||
c->guard_interval = GUARD_INTERVAL_1_32;
|
||||
break;
|
||||
case GUARD_INT_1_16:
|
||||
c->guard_interval = GUARD_INTERVAL_1_16;
|
||||
break;
|
||||
case GUARD_INT_1_8:
|
||||
c->guard_interval = GUARD_INTERVAL_1_8;
|
||||
break;
|
||||
case GUARD_INT_1_4:
|
||||
c->guard_interval = GUARD_INTERVAL_1_4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* extract transmission mode */
|
||||
switch (tps.transmission_mode) {
|
||||
case TRANS_MODE_2K:
|
||||
c->transmission_mode = TRANSMISSION_MODE_2K;
|
||||
break;
|
||||
case TRANS_MODE_8K:
|
||||
c->transmission_mode = TRANSMISSION_MODE_8K;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as102_fe_get_tune_settings(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *settings) {
|
||||
|
||||
settings->min_delay_ms = 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
int ret = 0;
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
struct as10x_tune_status tstate = { 0 };
|
||||
|
||||
/* send abilis command: GET_TUNE_STATUS */
|
||||
ret = state->ops->get_status(state->priv, &tstate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
state->signal_strength = tstate.signal_strength;
|
||||
state->ber = tstate.BER;
|
||||
|
||||
switch (tstate.tune_state) {
|
||||
case TUNE_STATUS_SIGNAL_DVB_OK:
|
||||
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
break;
|
||||
case TUNE_STATUS_STREAM_DETECTED:
|
||||
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC |
|
||||
FE_HAS_VITERBI;
|
||||
break;
|
||||
case TUNE_STATUS_STREAM_TUNED:
|
||||
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC |
|
||||
FE_HAS_LOCK | FE_HAS_VITERBI;
|
||||
break;
|
||||
default:
|
||||
*status = TUNE_STATUS_NOT_TUNED;
|
||||
}
|
||||
|
||||
pr_debug("as102: tuner status: 0x%02x, strength %d, per: %d, ber: %d\n",
|
||||
tstate.tune_state, tstate.signal_strength,
|
||||
tstate.PER, tstate.BER);
|
||||
|
||||
if (!(*status & FE_HAS_LOCK)) {
|
||||
memset(&state->demod_stats, 0, sizeof(state->demod_stats));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = state->ops->get_stats(state->priv, &state->demod_stats);
|
||||
if (ret < 0)
|
||||
memset(&state->demod_stats, 0, sizeof(state->demod_stats));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note:
|
||||
* - in AS102 SNR=MER
|
||||
* - the SNR will be returned in linear terms, i.e. not in dB
|
||||
* - the accuracy equals ±2dB for a SNR range from 4dB to 30dB
|
||||
* - the accuracy is >2dB for SNR values outside this range
|
||||
*/
|
||||
static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
{
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
|
||||
*snr = state->demod_stats.mer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
|
||||
*ber = state->ber;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as102_fe_read_signal_strength(struct dvb_frontend *fe,
|
||||
u16 *strength)
|
||||
{
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
|
||||
*strength = (((0xffff * 400) * state->signal_strength + 41000) * 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||
{
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
|
||||
if (state->demod_stats.has_started)
|
||||
*ucblocks = state->demod_stats.bad_frame_count;
|
||||
else
|
||||
*ucblocks = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
|
||||
{
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
|
||||
return state->ops->stream_ctrl(state->priv, acquire,
|
||||
state->elna_cfg);
|
||||
}
|
||||
|
||||
static void as102_fe_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct as102_state *state = fe->demodulator_priv;
|
||||
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
|
||||
static struct dvb_frontend_ops as102_fe_ops = {
|
||||
.delsys = { SYS_DVBT },
|
||||
.info = {
|
||||
.name = "Abilis AS102 DVB-T",
|
||||
.frequency_min = 174000000,
|
||||
.frequency_max = 862000000,
|
||||
.frequency_stepsize = 166667,
|
||||
.caps = FE_CAN_INVERSION_AUTO
|
||||
| FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
|
||||
| FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO
|
||||
| FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK
|
||||
| FE_CAN_QAM_AUTO
|
||||
| FE_CAN_TRANSMISSION_MODE_AUTO
|
||||
| FE_CAN_GUARD_INTERVAL_AUTO
|
||||
| FE_CAN_HIERARCHY_AUTO
|
||||
| FE_CAN_RECOVER
|
||||
| FE_CAN_MUTE_TS
|
||||
},
|
||||
|
||||
.set_frontend = as102_fe_set_frontend,
|
||||
.get_frontend = as102_fe_get_frontend,
|
||||
.get_tune_settings = as102_fe_get_tune_settings,
|
||||
|
||||
.read_status = as102_fe_read_status,
|
||||
.read_snr = as102_fe_read_snr,
|
||||
.read_ber = as102_fe_read_ber,
|
||||
.read_signal_strength = as102_fe_read_signal_strength,
|
||||
.read_ucblocks = as102_fe_read_ucblocks,
|
||||
.ts_bus_ctrl = as102_fe_ts_bus_ctrl,
|
||||
.release = as102_fe_release,
|
||||
};
|
||||
|
||||
struct dvb_frontend *as102_attach(const char *name,
|
||||
const struct as102_fe_ops *ops,
|
||||
void *priv,
|
||||
uint8_t elna_cfg)
|
||||
{
|
||||
struct as102_state *state;
|
||||
struct dvb_frontend *fe;
|
||||
|
||||
state = kzalloc(sizeof(struct as102_state), GFP_KERNEL);
|
||||
if (state == NULL) {
|
||||
pr_err("%s: unable to allocate memory for state\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
fe = &state->frontend;
|
||||
fe->demodulator_priv = state;
|
||||
state->ops = ops;
|
||||
state->priv = priv;
|
||||
state->elna_cfg = elna_cfg;
|
||||
|
||||
/* init frontend callback ops */
|
||||
memcpy(&fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops));
|
||||
strncpy(fe->ops.info.name, name, sizeof(fe->ops.info.name));
|
||||
|
||||
return fe;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(as102_attach);
|
||||
|
||||
MODULE_DESCRIPTION("as102-fe");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
|
29
drivers/media/dvb-frontends/as102_fe.h
Normal file
29
drivers/media/dvb-frontends/as102_fe.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Abilis Systems Single DVB-T Receiver
|
||||
* Copyright (C) 2014 Mauro Carvalho Chehab <m.chehab@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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.
|
||||
*/
|
||||
|
||||
#include "as102_fe_types.h"
|
||||
|
||||
struct as102_fe_ops {
|
||||
int (*set_tune)(void *priv, struct as10x_tune_args *tune_args);
|
||||
int (*get_tps)(void *priv, struct as10x_tps *tps);
|
||||
int (*get_status)(void *priv, struct as10x_tune_status *tstate);
|
||||
int (*get_stats)(void *priv, struct as10x_demod_stats *demod_stats);
|
||||
int (*stream_ctrl)(void *priv, int acquire, uint32_t elna_cfg);
|
||||
};
|
||||
|
||||
struct dvb_frontend *as102_attach(const char *name,
|
||||
const struct as102_fe_ops *ops,
|
||||
void *priv,
|
||||
uint8_t elna_cfg);
|
@ -11,16 +11,10 @@
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _AS10X_TYPES_H_
|
||||
#define _AS10X_TYPES_H_
|
||||
|
||||
#include "as10x_handle.h"
|
||||
|
||||
/*********************************/
|
||||
/* MACRO DEFINITIONS */
|
||||
/*********************************/
|
@ -639,12 +639,12 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe)
|
||||
err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
|
||||
return ret;
|
||||
}
|
||||
deb_info("got firmware: %zd\n",fw->size);
|
||||
deb_info("got firmware: %zu\n", fw->size);
|
||||
|
||||
b = fw->data;
|
||||
for (i = 0; i < fw->size;) {
|
||||
addr = le16_to_cpu( *( (u16 *)&b[i] ) );
|
||||
len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
|
||||
addr = le16_to_cpu(*((__le16 *)&b[i]));
|
||||
len = le16_to_cpu(*((__le16 *)&b[i+2]));
|
||||
deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
|
||||
if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
|
||||
err("firmware download failed: %d\n",ret);
|
||||
|
@ -65,7 +65,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
|
||||
}
|
||||
|
||||
priv->delivery_system = SYS_DVBC_ANNEX_A;
|
||||
priv->ber_running = 0; /* tune stops BER counter */
|
||||
priv->ber_running = false; /* tune stops BER counter */
|
||||
|
||||
/* program IF frequency */
|
||||
if (fe->ops.tuner_ops.get_if_frequency) {
|
||||
@ -168,7 +168,7 @@ int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
|
||||
start_ber = 1;
|
||||
}
|
||||
} else {
|
||||
priv->ber_running = 1;
|
||||
priv->ber_running = true;
|
||||
start_ber = 1;
|
||||
}
|
||||
|
||||
|
@ -564,10 +564,10 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
|
||||
|
||||
/* check if we have a valid signal */
|
||||
if (status & FE_HAS_LOCK) {
|
||||
priv->last_tune_failed = 0;
|
||||
priv->last_tune_failed = false;
|
||||
return DVBFE_ALGO_SEARCH_SUCCESS;
|
||||
} else {
|
||||
priv->last_tune_failed = 1;
|
||||
priv->last_tune_failed = true;
|
||||
return DVBFE_ALGO_SEARCH_AGAIN;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
|
||||
}
|
||||
|
||||
priv->delivery_system = SYS_DVBT;
|
||||
priv->ber_running = 0; /* tune stops BER counter */
|
||||
priv->ber_running = false; /* tune stops BER counter */
|
||||
|
||||
/* program IF frequency */
|
||||
if (fe->ops.tuner_ops.get_if_frequency) {
|
||||
@ -272,7 +272,7 @@ int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber)
|
||||
start_ber = 1;
|
||||
}
|
||||
} else {
|
||||
priv->ber_running = 1;
|
||||
priv->ber_running = true;
|
||||
start_ber = 1;
|
||||
}
|
||||
|
||||
|
@ -2559,7 +2559,7 @@ static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode)
|
||||
dib7000p_write_word(state, 1288, reg_1288);
|
||||
}
|
||||
|
||||
int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
|
||||
static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
u16 reg_1287;
|
||||
|
@ -2174,7 +2174,7 @@ int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr,
|
||||
u32 addr,
|
||||
u32 *data, u32 flags)
|
||||
{
|
||||
u8 buf[sizeof(*data)];
|
||||
u8 buf[sizeof(*data)] = { 0 };
|
||||
int rc = -EIO;
|
||||
u32 word = 0;
|
||||
|
||||
@ -4193,7 +4193,7 @@ int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr,
|
||||
u32 addr,
|
||||
u16 *data, u32 flags)
|
||||
{
|
||||
u8 buf[2];
|
||||
u8 buf[2] = { 0 };
|
||||
int rc = -EIO;
|
||||
u16 word = 0;
|
||||
|
||||
@ -10667,7 +10667,7 @@ ctrl_sig_quality(struct drx_demod_instance *demod,
|
||||
enum drx_standard standard = ext_attr->standard;
|
||||
int rc;
|
||||
u32 ber, cnt, err, pkt;
|
||||
u16 mer, strength;
|
||||
u16 mer, strength = 0;
|
||||
|
||||
rc = get_sig_strength(demod, &strength);
|
||||
if (rc < 0) {
|
||||
@ -11602,7 +11602,7 @@ static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words)
|
||||
u32 carry = 0;
|
||||
|
||||
while (i < nr_words) {
|
||||
crc_word |= (u32)be16_to_cpu(*(u32 *)(block_data));
|
||||
crc_word |= (u32)be16_to_cpu(*(__be16 *)(block_data));
|
||||
for (j = 0; j < 16; j++) {
|
||||
crc_word <<= 1;
|
||||
if (carry != 0)
|
||||
@ -11629,7 +11629,7 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
|
||||
int i;
|
||||
unsigned count = 2 * sizeof(u16);
|
||||
u32 mc_dev_type, mc_version, mc_base_version;
|
||||
u16 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data + sizeof(u16)));
|
||||
u16 mc_nr_of_blks = be16_to_cpu(*(__be16 *)(mc_data + sizeof(u16)));
|
||||
|
||||
/*
|
||||
* Scan microcode blocks first for version info
|
||||
@ -11647,13 +11647,13 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
|
||||
goto eof;
|
||||
|
||||
/* Process block header */
|
||||
block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data + count));
|
||||
block_hdr.addr = be32_to_cpu(*(__be32 *)(mc_data + count));
|
||||
count += sizeof(u32);
|
||||
block_hdr.size = be16_to_cpu(*(u32 *)(mc_data + count));
|
||||
block_hdr.size = be16_to_cpu(*(__be16 *)(mc_data + count));
|
||||
count += sizeof(u16);
|
||||
block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data + count));
|
||||
block_hdr.flags = be16_to_cpu(*(__be16 *)(mc_data + count));
|
||||
count += sizeof(u16);
|
||||
block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data + count));
|
||||
block_hdr.CRC = be16_to_cpu(*(__be16 *)(mc_data + count));
|
||||
count += sizeof(u16);
|
||||
|
||||
pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
|
||||
@ -11667,7 +11667,7 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
|
||||
if (block_hdr.addr + sizeof(u16) > size)
|
||||
goto eof;
|
||||
|
||||
auxtype = be16_to_cpu(*(u32 *)(auxblk));
|
||||
auxtype = be16_to_cpu(*(__be16 *)(auxblk));
|
||||
|
||||
/* Aux block. Check type */
|
||||
if (DRX_ISMCVERTYPE(auxtype)) {
|
||||
@ -11675,11 +11675,11 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
|
||||
goto eof;
|
||||
|
||||
auxblk += sizeof(u16);
|
||||
mc_dev_type = be32_to_cpu(*(u32 *)(auxblk));
|
||||
mc_dev_type = be32_to_cpu(*(__be32 *)(auxblk));
|
||||
auxblk += sizeof(u32);
|
||||
mc_version = be32_to_cpu(*(u32 *)(auxblk));
|
||||
mc_version = be32_to_cpu(*(__be32 *)(auxblk));
|
||||
auxblk += sizeof(u32);
|
||||
mc_base_version = be32_to_cpu(*(u32 *)(auxblk));
|
||||
mc_base_version = be32_to_cpu(*(__be32 *)(auxblk));
|
||||
|
||||
DRX_ATTR_MCRECORD(demod).aux_type = auxtype;
|
||||
DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type;
|
||||
@ -11765,9 +11765,9 @@ static int drx_ctrl_u_code(struct drx_demod_instance *demod,
|
||||
|
||||
mc_data = (void *)mc_data_init;
|
||||
/* Check data */
|
||||
mc_magic_word = be16_to_cpu(*(u32 *)(mc_data));
|
||||
mc_magic_word = be16_to_cpu(*(__be16 *)(mc_data));
|
||||
mc_data += sizeof(u16);
|
||||
mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data));
|
||||
mc_nr_of_blks = be16_to_cpu(*(__be16 *)(mc_data));
|
||||
mc_data += sizeof(u16);
|
||||
|
||||
if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) {
|
||||
@ -11791,13 +11791,13 @@ static int drx_ctrl_u_code(struct drx_demod_instance *demod,
|
||||
u16 mc_block_nr_bytes = 0;
|
||||
|
||||
/* Process block header */
|
||||
block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data));
|
||||
block_hdr.addr = be32_to_cpu(*(__be32 *)(mc_data));
|
||||
mc_data += sizeof(u32);
|
||||
block_hdr.size = be16_to_cpu(*(u32 *)(mc_data));
|
||||
block_hdr.size = be16_to_cpu(*(__be16 *)(mc_data));
|
||||
mc_data += sizeof(u16);
|
||||
block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data));
|
||||
block_hdr.flags = be16_to_cpu(*(__be16 *)(mc_data));
|
||||
mc_data += sizeof(u16);
|
||||
block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data));
|
||||
block_hdr.CRC = be16_to_cpu(*(__be16 *)(mc_data));
|
||||
mc_data += sizeof(u16);
|
||||
|
||||
pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
|
||||
|
@ -2628,10 +2628,11 @@ static int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size)
|
||||
break;
|
||||
|
||||
/* Apply I2c address patch to B1 */
|
||||
if (!state->type_A && state->m_HiI2cPatch != NULL)
|
||||
if (!state->type_A && state->m_HiI2cPatch != NULL) {
|
||||
status = WriteTable(state, state->m_HiI2cPatch);
|
||||
if (status < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (state->type_A) {
|
||||
/* HI firmware patch for UIO readout,
|
||||
@ -2830,14 +2831,8 @@ static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status)
|
||||
static int drxd_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct drxd_state *state = fe->demodulator_priv;
|
||||
int err = 0;
|
||||
|
||||
/* if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */
|
||||
return DRXD_init(state, NULL, 0);
|
||||
|
||||
err = DRXD_init(state, state->fw->data, state->fw->size);
|
||||
release_firmware(state->fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
|
||||
|
@ -1028,7 +1028,7 @@ static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result)
|
||||
((state->m_hi_cfg_ctrl) &
|
||||
SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) ==
|
||||
SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ);
|
||||
if (powerdown_cmd == false) {
|
||||
if (!powerdown_cmd) {
|
||||
/* Wait until command rdy */
|
||||
u32 retry_count = 0;
|
||||
u16 wait_cmd;
|
||||
@ -1129,7 +1129,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable)
|
||||
if (status < 0)
|
||||
goto error;
|
||||
|
||||
if (mpeg_enable == false) {
|
||||
if (!mpeg_enable) {
|
||||
/* Set MPEG TS pads to inputmode */
|
||||
status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000);
|
||||
if (status < 0)
|
||||
@ -1190,7 +1190,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable)
|
||||
if (status < 0)
|
||||
goto error;
|
||||
|
||||
if (state->m_enable_parallel == true) {
|
||||
if (state->m_enable_parallel) {
|
||||
/* parallel -> enable MD1 to MD7 */
|
||||
status = write16(state, SIO_PDR_MD1_CFG__A,
|
||||
sio_pdr_mdx_cfg);
|
||||
@ -1392,7 +1392,7 @@ static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable)
|
||||
|
||||
dprintk(1, "\n");
|
||||
|
||||
if (enable == false) {
|
||||
if (!enable) {
|
||||
desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF;
|
||||
desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN;
|
||||
}
|
||||
@ -2012,7 +2012,7 @@ static int mpegts_dto_setup(struct drxk_state *state,
|
||||
goto error;
|
||||
fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M);
|
||||
fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
|
||||
if (state->m_insert_rs_byte == true) {
|
||||
if (state->m_insert_rs_byte) {
|
||||
/* enable parity symbol forward */
|
||||
fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M;
|
||||
/* MVAL disable during parity bytes */
|
||||
@ -2023,7 +2023,7 @@ static int mpegts_dto_setup(struct drxk_state *state,
|
||||
|
||||
/* Check serial or parallel output */
|
||||
fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
|
||||
if (state->m_enable_parallel == false) {
|
||||
if (!state->m_enable_parallel) {
|
||||
/* MPEG data output is serial -> set ipr_mode[0] */
|
||||
fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
|
||||
}
|
||||
@ -2136,19 +2136,19 @@ static int mpegts_configure_polarity(struct drxk_state *state)
|
||||
|
||||
/* Control selective inversion of output bits */
|
||||
fec_oc_reg_ipr_invert &= (~(invert_data_mask));
|
||||
if (state->m_invert_data == true)
|
||||
if (state->m_invert_data)
|
||||
fec_oc_reg_ipr_invert |= invert_data_mask;
|
||||
fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M));
|
||||
if (state->m_invert_err == true)
|
||||
if (state->m_invert_err)
|
||||
fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M;
|
||||
fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
|
||||
if (state->m_invert_str == true)
|
||||
if (state->m_invert_str)
|
||||
fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M;
|
||||
fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
|
||||
if (state->m_invert_val == true)
|
||||
if (state->m_invert_val)
|
||||
fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M;
|
||||
fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
|
||||
if (state->m_invert_clk == true)
|
||||
if (state->m_invert_clk)
|
||||
fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M;
|
||||
|
||||
return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert);
|
||||
@ -2220,12 +2220,13 @@ static int set_agc_rf(struct drxk_state *state,
|
||||
}
|
||||
|
||||
/* Set TOP, only if IF-AGC is in AUTO mode */
|
||||
if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO)
|
||||
if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) {
|
||||
status = write16(state,
|
||||
SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
|
||||
p_agc_cfg->top);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Cut-Off current */
|
||||
status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A,
|
||||
@ -3352,7 +3353,7 @@ static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled)
|
||||
int status;
|
||||
|
||||
dprintk(1, "\n");
|
||||
if (*enabled == true)
|
||||
if (*enabled)
|
||||
status = write16(state, IQM_CF_BYPASSDET__A, 0);
|
||||
else
|
||||
status = write16(state, IQM_CF_BYPASSDET__A, 1);
|
||||
@ -3368,7 +3369,7 @@ static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled)
|
||||
int status;
|
||||
|
||||
dprintk(1, "\n");
|
||||
if (*enabled == true) {
|
||||
if (*enabled) {
|
||||
/* write mask to 1 */
|
||||
status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A,
|
||||
DEFAULT_FR_THRES_8K);
|
||||
@ -6794,11 +6795,11 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
|
||||
state->enable_merr_cfg = config->enable_merr_cfg;
|
||||
|
||||
if (config->dynamic_clk) {
|
||||
state->m_dvbt_static_clk = 0;
|
||||
state->m_dvbc_static_clk = 0;
|
||||
state->m_dvbt_static_clk = false;
|
||||
state->m_dvbc_static_clk = false;
|
||||
} else {
|
||||
state->m_dvbt_static_clk = 1;
|
||||
state->m_dvbc_static_clk = 1;
|
||||
state->m_dvbt_static_clk = true;
|
||||
state->m_dvbc_static_clk = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -159,6 +159,7 @@ static int m88ds3103_wr_reg_val_tab(struct m88ds3103_priv *priv,
|
||||
{
|
||||
int ret, i, j;
|
||||
u8 buf[83];
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
|
||||
|
||||
if (tab_len > 83) {
|
||||
@ -247,8 +248,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
|
||||
u8 u8tmp, u8tmp1, u8tmp2;
|
||||
u8 buf[2];
|
||||
u16 u16tmp, divide_ratio;
|
||||
u32 tuner_frequency, target_mclk, ts_clk;
|
||||
u32 tuner_frequency, target_mclk;
|
||||
s32 s32tmp;
|
||||
|
||||
dev_dbg(&priv->i2c->dev,
|
||||
"%s: delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n",
|
||||
__func__, c->delivery_system,
|
||||
@ -316,9 +318,6 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
|
||||
target_mclk = 144000;
|
||||
break;
|
||||
case M88DS3103_TS_PARALLEL:
|
||||
case M88DS3103_TS_PARALLEL_12:
|
||||
case M88DS3103_TS_PARALLEL_16:
|
||||
case M88DS3103_TS_PARALLEL_19_2:
|
||||
case M88DS3103_TS_CI:
|
||||
if (c->symbol_rate < 18000000)
|
||||
target_mclk = 96000;
|
||||
@ -352,33 +351,17 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
|
||||
switch (priv->cfg->ts_mode) {
|
||||
case M88DS3103_TS_SERIAL:
|
||||
u8tmp1 = 0x00;
|
||||
ts_clk = 0;
|
||||
u8tmp = 0x46;
|
||||
u8tmp = 0x06;
|
||||
break;
|
||||
case M88DS3103_TS_SERIAL_D7:
|
||||
u8tmp1 = 0x20;
|
||||
ts_clk = 0;
|
||||
u8tmp = 0x46;
|
||||
u8tmp = 0x06;
|
||||
break;
|
||||
case M88DS3103_TS_PARALLEL:
|
||||
ts_clk = 24000;
|
||||
u8tmp = 0x42;
|
||||
break;
|
||||
case M88DS3103_TS_PARALLEL_12:
|
||||
ts_clk = 12000;
|
||||
u8tmp = 0x42;
|
||||
break;
|
||||
case M88DS3103_TS_PARALLEL_16:
|
||||
ts_clk = 16000;
|
||||
u8tmp = 0x42;
|
||||
break;
|
||||
case M88DS3103_TS_PARALLEL_19_2:
|
||||
ts_clk = 19200;
|
||||
u8tmp = 0x42;
|
||||
u8tmp = 0x02;
|
||||
break;
|
||||
case M88DS3103_TS_CI:
|
||||
ts_clk = 6000;
|
||||
u8tmp = 0x43;
|
||||
u8tmp = 0x03;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", __func__);
|
||||
@ -386,6 +369,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (priv->cfg->ts_clk_pol)
|
||||
u8tmp |= 0x40;
|
||||
|
||||
/* TS mode */
|
||||
ret = m88ds3103_wr_reg(priv, 0xfd, u8tmp);
|
||||
if (ret)
|
||||
@ -399,8 +385,8 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ts_clk) {
|
||||
divide_ratio = DIV_ROUND_UP(target_mclk, ts_clk);
|
||||
if (priv->cfg->ts_clk) {
|
||||
divide_ratio = DIV_ROUND_UP(target_mclk, priv->cfg->ts_clk);
|
||||
u8tmp1 = divide_ratio / 2;
|
||||
u8tmp2 = DIV_ROUND_UP(divide_ratio, 2);
|
||||
} else {
|
||||
@ -411,7 +397,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
|
||||
|
||||
dev_dbg(&priv->i2c->dev,
|
||||
"%s: target_mclk=%d ts_clk=%d divide_ratio=%d\n",
|
||||
__func__, target_mclk, ts_clk, divide_ratio);
|
||||
__func__, target_mclk, priv->cfg->ts_clk, divide_ratio);
|
||||
|
||||
u8tmp1--;
|
||||
u8tmp2--;
|
||||
@ -536,6 +522,7 @@ static int m88ds3103_init(struct dvb_frontend *fe)
|
||||
const struct firmware *fw = NULL;
|
||||
u8 *fw_file = M88DS3103_FIRMWARE;
|
||||
u8 u8tmp;
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
|
||||
|
||||
/* set cold state by default */
|
||||
@ -648,6 +635,7 @@ static int m88ds3103_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct m88ds3103_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
|
||||
|
||||
priv->delivery_system = SYS_UNDEFINED;
|
||||
@ -682,6 +670,7 @@ static int m88ds3103_get_frontend(struct dvb_frontend *fe)
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret;
|
||||
u8 buf[3];
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
|
||||
|
||||
if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
|
||||
@ -857,6 +846,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
u8 buf[3];
|
||||
u16 noise, signal;
|
||||
u32 noise_tot, signal_tot;
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
|
||||
/* reports SNR in resolution of 0.1 dB */
|
||||
|
||||
@ -933,6 +923,7 @@ static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
int ret;
|
||||
unsigned int utmp;
|
||||
u8 buf[3], u8tmp;
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
|
||||
|
||||
switch (c->delivery_system) {
|
||||
@ -1013,6 +1004,7 @@ static int m88ds3103_set_tone(struct dvb_frontend *fe,
|
||||
struct m88ds3103_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 u8tmp, tone, reg_a1_mask;
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s: fe_sec_tone_mode=%d\n", __func__,
|
||||
fe_sec_tone_mode);
|
||||
|
||||
@ -1053,12 +1045,64 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m88ds3103_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t fe_sec_voltage)
|
||||
{
|
||||
struct m88ds3103_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 u8tmp;
|
||||
bool voltage_sel, voltage_dis;
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s: fe_sec_voltage=%d\n", __func__,
|
||||
fe_sec_voltage);
|
||||
|
||||
if (!priv->warm) {
|
||||
ret = -EAGAIN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (fe_sec_voltage) {
|
||||
case SEC_VOLTAGE_18:
|
||||
voltage_sel = true;
|
||||
voltage_dis = false;
|
||||
break;
|
||||
case SEC_VOLTAGE_13:
|
||||
voltage_sel = false;
|
||||
voltage_dis = false;
|
||||
break;
|
||||
case SEC_VOLTAGE_OFF:
|
||||
voltage_sel = false;
|
||||
voltage_dis = true;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* output pin polarity */
|
||||
voltage_sel ^= priv->cfg->lnb_hv_pol;
|
||||
voltage_dis ^= priv->cfg->lnb_en_pol;
|
||||
|
||||
u8tmp = voltage_dis << 1 | voltage_sel << 0;
|
||||
ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0x03);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe,
|
||||
struct dvb_diseqc_master_cmd *diseqc_cmd)
|
||||
{
|
||||
struct m88ds3103_priv *priv = fe->demodulator_priv;
|
||||
int ret, i;
|
||||
u8 u8tmp;
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s: msg=%*ph\n", __func__,
|
||||
diseqc_cmd->msg_len, diseqc_cmd->msg);
|
||||
|
||||
@ -1130,6 +1174,7 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
|
||||
struct m88ds3103_priv *priv = fe->demodulator_priv;
|
||||
int ret, i;
|
||||
u8 u8tmp, burst;
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__,
|
||||
fe_sec_mini_cmd);
|
||||
|
||||
@ -1202,6 +1247,7 @@ static int m88ds3103_get_tune_settings(struct dvb_frontend *fe,
|
||||
static void m88ds3103_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct m88ds3103_priv *priv = fe->demodulator_priv;
|
||||
|
||||
i2c_del_mux_adapter(priv->i2c_adapter);
|
||||
kfree(priv);
|
||||
}
|
||||
@ -1370,6 +1416,7 @@ static struct dvb_frontend_ops m88ds3103_ops = {
|
||||
.diseqc_send_burst = m88ds3103_diseqc_send_burst,
|
||||
|
||||
.set_tone = m88ds3103_set_tone,
|
||||
.set_voltage = m88ds3103_set_voltage,
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
||||
|
@ -47,13 +47,22 @@ struct m88ds3103_config {
|
||||
*/
|
||||
#define M88DS3103_TS_SERIAL 0 /* TS output pin D0, normal */
|
||||
#define M88DS3103_TS_SERIAL_D7 1 /* TS output pin D7 */
|
||||
#define M88DS3103_TS_PARALLEL 2 /* 24 MHz, normal */
|
||||
#define M88DS3103_TS_PARALLEL_12 3 /* 12 MHz */
|
||||
#define M88DS3103_TS_PARALLEL_16 4 /* 16 MHz */
|
||||
#define M88DS3103_TS_PARALLEL_19_2 5 /* 19.2 MHz */
|
||||
#define M88DS3103_TS_CI 6 /* 6 MHz */
|
||||
#define M88DS3103_TS_PARALLEL 2 /* TS Parallel mode */
|
||||
#define M88DS3103_TS_CI 3 /* TS CI Mode */
|
||||
u8 ts_mode;
|
||||
|
||||
/*
|
||||
* TS clk in KHz
|
||||
* Default: 0.
|
||||
*/
|
||||
u32 ts_clk;
|
||||
|
||||
/*
|
||||
* TS clk polarity.
|
||||
* Default: 0. 1-active at falling edge; 0-active at rising edge.
|
||||
*/
|
||||
u8 ts_clk_pol:1;
|
||||
|
||||
/*
|
||||
* spectrum inversion
|
||||
* Default: 0
|
||||
@ -86,6 +95,22 @@ struct m88ds3103_config {
|
||||
* Default: none, must set
|
||||
*/
|
||||
u8 agc;
|
||||
|
||||
/*
|
||||
* LNB H/V pin polarity
|
||||
* Default: 0.
|
||||
* 1: pin high set to VOLTAGE_13, pin low to set VOLTAGE_18.
|
||||
* 0: pin high set to VOLTAGE_18, pin low to set VOLTAGE_13.
|
||||
*/
|
||||
u8 lnb_hv_pol:1;
|
||||
|
||||
/*
|
||||
* LNB enable pin polarity
|
||||
* Default: 0.
|
||||
* 1: pin high to enable, pin low to disable.
|
||||
* 0: pin high to disable, pin low to enable.
|
||||
*/
|
||||
u8 lnb_en_pol:1;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "mb86a16.h"
|
||||
#include "mb86a16_priv.h"
|
||||
|
||||
unsigned int verbose = 5;
|
||||
static unsigned int verbose = 5;
|
||||
module_param(verbose, int, 0644);
|
||||
|
||||
#define ABS(x) ((x) < 0 ? (-x) : (x))
|
||||
@ -115,9 +115,11 @@ static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val)
|
||||
};
|
||||
ret = i2c_transfer(state->i2c_adap, msg, 2);
|
||||
if (ret != 2) {
|
||||
dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)",
|
||||
dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=%i)",
|
||||
reg, ret);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
*val = b1[0];
|
||||
|
@ -33,7 +33,7 @@ enum mb86a20s_bandwidth {
|
||||
MB86A20S_3SEG = 3,
|
||||
};
|
||||
|
||||
u8 mb86a20s_subchannel[] = {
|
||||
static u8 mb86a20s_subchannel[] = {
|
||||
0xb0, 0xc0, 0xd0, 0xe0,
|
||||
0xf0, 0x00, 0x10, 0x20,
|
||||
};
|
||||
@ -1228,7 +1228,7 @@ struct linear_segments {
|
||||
* All tables below return a dB/1000 measurement
|
||||
*/
|
||||
|
||||
static struct linear_segments cnr_to_db_table[] = {
|
||||
static const struct linear_segments cnr_to_db_table[] = {
|
||||
{ 19648, 0},
|
||||
{ 18187, 1000},
|
||||
{ 16534, 2000},
|
||||
@ -1262,7 +1262,7 @@ static struct linear_segments cnr_to_db_table[] = {
|
||||
{ 788, 30000},
|
||||
};
|
||||
|
||||
static struct linear_segments cnr_64qam_table[] = {
|
||||
static const struct linear_segments cnr_64qam_table[] = {
|
||||
{ 3922688, 0},
|
||||
{ 3920384, 1000},
|
||||
{ 3902720, 2000},
|
||||
@ -1296,7 +1296,7 @@ static struct linear_segments cnr_64qam_table[] = {
|
||||
{ 388864, 30000},
|
||||
};
|
||||
|
||||
static struct linear_segments cnr_16qam_table[] = {
|
||||
static const struct linear_segments cnr_16qam_table[] = {
|
||||
{ 5314816, 0},
|
||||
{ 5219072, 1000},
|
||||
{ 5118720, 2000},
|
||||
@ -1330,7 +1330,7 @@ static struct linear_segments cnr_16qam_table[] = {
|
||||
{ 95744, 30000},
|
||||
};
|
||||
|
||||
struct linear_segments cnr_qpsk_table[] = {
|
||||
static const struct linear_segments cnr_qpsk_table[] = {
|
||||
{ 2834176, 0},
|
||||
{ 2683648, 1000},
|
||||
{ 2536960, 2000},
|
||||
@ -1364,7 +1364,7 @@ struct linear_segments cnr_qpsk_table[] = {
|
||||
{ 11520, 30000},
|
||||
};
|
||||
|
||||
static u32 interpolate_value(u32 value, struct linear_segments *segments,
|
||||
static u32 interpolate_value(u32 value, const struct linear_segments *segments,
|
||||
unsigned len)
|
||||
{
|
||||
u64 tmp64;
|
||||
@ -1448,7 +1448,7 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe)
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
u32 mer, cnr;
|
||||
int rc, val, layer;
|
||||
struct linear_segments *segs;
|
||||
const struct linear_segments *segs;
|
||||
unsigned segs_len;
|
||||
|
||||
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
|
||||
|
@ -103,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
|
||||
|
||||
if (1 + count > sizeof(buf)) {
|
||||
printk(KERN_WARNING
|
||||
"mt312: write: len=%zd is too big!\n", count);
|
||||
"mt312: write: len=%zu is too big!\n", count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe,
|
||||
u8 tudata[585];
|
||||
int i;
|
||||
|
||||
dprintk("Firmware is %zd bytes\n",fw->size);
|
||||
dprintk("Firmware is %zu bytes\n", fw->size);
|
||||
|
||||
/* Get eprom data */
|
||||
tudata[0] = 17;
|
||||
|
@ -936,7 +936,7 @@ static void rtl2832_i2c_gate_work(struct work_struct *work)
|
||||
if (ret != 1)
|
||||
goto err;
|
||||
|
||||
priv->i2c_gate_state = 0;
|
||||
priv->i2c_gate_state = false;
|
||||
|
||||
return;
|
||||
err:
|
||||
|
@ -329,7 +329,7 @@ static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
|
||||
static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
|
||||
struct rtl2832_sdr_state *s)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
unsigned long flags;
|
||||
struct rtl2832_sdr_frame_buf *buf = NULL;
|
||||
|
||||
spin_lock_irqsave(&s->queued_bufs_lock, flags);
|
||||
@ -365,17 +365,19 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
|
||||
dst_len = 0;
|
||||
}
|
||||
|
||||
/* calculate samping rate and output it in 10 seconds intervals */
|
||||
/* calculate sample rate and output it in 10 seconds intervals */
|
||||
if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
|
||||
#define MSECS 10000UL
|
||||
#define MSECS 10000UL
|
||||
unsigned int msecs = jiffies_to_msecs(jiffies -
|
||||
s->jiffies_next + msecs_to_jiffies(MSECS));
|
||||
unsigned int samples = s->sample - s->sample_measured;
|
||||
|
||||
s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
|
||||
s->sample_measured = s->sample;
|
||||
dev_dbg(&s->udev->dev,
|
||||
"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
|
||||
src_len, samples, MSECS,
|
||||
samples * 1000UL / MSECS);
|
||||
"slen=%u samples=%u msecs=%u sample rate=%lu\n",
|
||||
src_len, samples, msecs,
|
||||
samples * 1000UL / msecs);
|
||||
}
|
||||
|
||||
/* total number of I+Q pairs */
|
||||
@ -394,8 +396,8 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
|
||||
struct rtl2832_sdr_frame_buf *fbuf;
|
||||
|
||||
dev_dbg_ratelimited(&s->udev->dev,
|
||||
"%s: status=%d length=%d/%d errors=%d\n",
|
||||
__func__, urb->status, urb->actual_length,
|
||||
"status=%d length=%d/%d errors=%d\n",
|
||||
urb->status, urb->actual_length,
|
||||
urb->transfer_buffer_length, urb->error_count);
|
||||
|
||||
switch (urb->status) {
|
||||
@ -443,7 +445,7 @@ static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *s)
|
||||
int i;
|
||||
|
||||
for (i = s->urbs_submitted - 1; i >= 0; i--) {
|
||||
dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
|
||||
dev_dbg(&s->udev->dev, "kill urb=%d\n", i);
|
||||
/* stop the URB */
|
||||
usb_kill_urb(s->urb_list[i]);
|
||||
}
|
||||
@ -457,7 +459,7 @@ static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *s)
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < s->urbs_initialized; i++) {
|
||||
dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
|
||||
dev_dbg(&s->udev->dev, "submit urb=%d\n", i);
|
||||
ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
|
||||
if (ret) {
|
||||
dev_err(&s->udev->dev,
|
||||
@ -477,8 +479,7 @@ static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *s)
|
||||
if (s->flags & USB_STATE_URB_BUF) {
|
||||
while (s->buf_num) {
|
||||
s->buf_num--;
|
||||
dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
|
||||
__func__, s->buf_num);
|
||||
dev_dbg(&s->udev->dev, "free buf=%d\n", s->buf_num);
|
||||
usb_free_coherent(s->udev, s->buf_size,
|
||||
s->buf_list[s->buf_num],
|
||||
s->dma_addr[s->buf_num]);
|
||||
@ -494,24 +495,22 @@ static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *s)
|
||||
s->buf_num = 0;
|
||||
s->buf_size = BULK_BUFFER_SIZE;
|
||||
|
||||
dev_dbg(&s->udev->dev,
|
||||
"%s: all in all I will use %u bytes for streaming\n",
|
||||
__func__, MAX_BULK_BUFS * BULK_BUFFER_SIZE);
|
||||
dev_dbg(&s->udev->dev, "all in all I will use %u bytes for streaming\n",
|
||||
MAX_BULK_BUFS * BULK_BUFFER_SIZE);
|
||||
|
||||
for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
|
||||
s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
|
||||
BULK_BUFFER_SIZE, GFP_ATOMIC,
|
||||
&s->dma_addr[s->buf_num]);
|
||||
if (!s->buf_list[s->buf_num]) {
|
||||
dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
|
||||
__func__, s->buf_num);
|
||||
dev_dbg(&s->udev->dev, "alloc buf=%d failed\n",
|
||||
s->buf_num);
|
||||
rtl2832_sdr_free_stream_bufs(s);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
|
||||
__func__, s->buf_num,
|
||||
s->buf_list[s->buf_num],
|
||||
dev_dbg(&s->udev->dev, "alloc buf=%d %p (dma %llu)\n",
|
||||
s->buf_num, s->buf_list[s->buf_num],
|
||||
(long long)s->dma_addr[s->buf_num]);
|
||||
s->flags |= USB_STATE_URB_BUF;
|
||||
}
|
||||
@ -527,8 +526,7 @@ static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s)
|
||||
|
||||
for (i = s->urbs_initialized - 1; i >= 0; i--) {
|
||||
if (s->urb_list[i]) {
|
||||
dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
|
||||
__func__, i);
|
||||
dev_dbg(&s->udev->dev, "free urb=%d\n", i);
|
||||
/* free the URBs */
|
||||
usb_free_urb(s->urb_list[i]);
|
||||
}
|
||||
@ -544,10 +542,10 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s)
|
||||
|
||||
/* allocate the URBs */
|
||||
for (i = 0; i < MAX_BULK_BUFS; i++) {
|
||||
dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
|
||||
dev_dbg(&s->udev->dev, "alloc urb=%d\n", i);
|
||||
s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!s->urb_list[i]) {
|
||||
dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "failed\n");
|
||||
for (j = 0; j < i; j++)
|
||||
usb_free_urb(s->urb_list[j]);
|
||||
return -ENOMEM;
|
||||
@ -570,9 +568,9 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s)
|
||||
/* Must be called with vb_queue_lock hold */
|
||||
static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
spin_lock_irqsave(&s->queued_bufs_lock, flags);
|
||||
while (!list_empty(&s->queued_bufs)) {
|
||||
@ -591,7 +589,7 @@ static void rtl2832_sdr_release_sec(struct dvb_frontend *fe)
|
||||
{
|
||||
struct rtl2832_sdr_state *s = fe->sec_priv;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
mutex_lock(&s->vb_queue_lock);
|
||||
mutex_lock(&s->v4l2_lock);
|
||||
@ -613,7 +611,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
|
||||
{
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
|
||||
strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
|
||||
@ -631,15 +629,15 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
|
||||
{
|
||||
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
|
||||
dev_dbg(&s->udev->dev, "nbuffers=%d\n", *nbuffers);
|
||||
|
||||
/* Need at least 8 buffers */
|
||||
if (vq->num_buffers + *nbuffers < 8)
|
||||
*nbuffers = 8 - vq->num_buffers;
|
||||
*nplanes = 1;
|
||||
sizes[0] = PAGE_ALIGN(s->buffersize);
|
||||
dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
|
||||
__func__, *nbuffers, sizes[0]);
|
||||
dev_dbg(&s->udev->dev, "nbuffers=%d sizes[0]=%d\n",
|
||||
*nbuffers, sizes[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -659,7 +657,7 @@ static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
|
||||
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
|
||||
struct rtl2832_sdr_frame_buf *buf =
|
||||
container_of(vb, struct rtl2832_sdr_frame_buf, vb);
|
||||
unsigned long flags = 0;
|
||||
unsigned long flags;
|
||||
|
||||
/* Check the device has not disconnected between prep and queuing */
|
||||
if (!s->udev) {
|
||||
@ -681,7 +679,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
|
||||
u64 u64tmp;
|
||||
u32 u32tmp;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc);
|
||||
dev_dbg(&s->udev->dev, "f_adc=%u\n", s->f_adc);
|
||||
|
||||
if (!test_bit(POWER_ON, &s->flags))
|
||||
return 0;
|
||||
@ -715,8 +713,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
|
||||
u64tmp = -u64tmp;
|
||||
u32tmp = u64tmp & 0x3fffff;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: f_if=%u if_ctl=%08x\n",
|
||||
__func__, f_if, u32tmp);
|
||||
dev_dbg(&s->udev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp);
|
||||
|
||||
buf[0] = (u32tmp >> 16) & 0xff;
|
||||
buf[1] = (u32tmp >> 8) & 0xff;
|
||||
@ -903,7 +900,7 @@ static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
/* PID filter */
|
||||
ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1);
|
||||
@ -964,8 +961,8 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
|
||||
c->frequency = s->f_tuner;
|
||||
c->delivery_system = SYS_DVBT;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: frequency=%u bandwidth=%d\n",
|
||||
__func__, c->frequency, c->bandwidth_hz);
|
||||
dev_dbg(&s->udev->dev, "frequency=%u bandwidth=%d\n",
|
||||
c->frequency, c->bandwidth_hz);
|
||||
|
||||
if (!test_bit(POWER_ON, &s->flags))
|
||||
return 0;
|
||||
@ -980,7 +977,7 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
|
||||
{
|
||||
struct dvb_frontend *fe = s->fe;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
if (fe->ops.tuner_ops.init)
|
||||
fe->ops.tuner_ops.init(fe);
|
||||
@ -992,7 +989,7 @@ static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s)
|
||||
{
|
||||
struct dvb_frontend *fe = s->fe;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
if (fe->ops.tuner_ops.sleep)
|
||||
fe->ops.tuner_ops.sleep(fe);
|
||||
@ -1005,7 +1002,7 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
|
||||
int ret;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
if (!s->udev)
|
||||
return -ENODEV;
|
||||
@ -1054,7 +1051,7 @@ static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
|
||||
{
|
||||
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
mutex_lock(&s->v4l2_lock);
|
||||
|
||||
@ -1088,8 +1085,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
|
||||
{
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n",
|
||||
__func__, v->index, v->type);
|
||||
dev_dbg(&s->udev->dev, "index=%d type=%d\n", v->index, v->type);
|
||||
|
||||
if (v->index == 0) {
|
||||
strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name));
|
||||
@ -1115,7 +1111,7 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
|
||||
{
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
if (v->index > 1)
|
||||
return -EINVAL;
|
||||
@ -1127,8 +1123,8 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
|
||||
{
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
|
||||
__func__, band->tuner, band->type, band->index);
|
||||
dev_dbg(&s->udev->dev, "tuner=%d type=%d index=%d\n",
|
||||
band->tuner, band->type, band->index);
|
||||
|
||||
if (band->tuner == 0) {
|
||||
if (band->index >= ARRAY_SIZE(bands_adc))
|
||||
@ -1153,8 +1149,8 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
|
||||
__func__, f->tuner, f->type);
|
||||
dev_dbg(&s->udev->dev, "tuner=%d type=%d\n",
|
||||
f->tuner, f->type);
|
||||
|
||||
if (f->tuner == 0) {
|
||||
f->frequency = s->f_adc;
|
||||
@ -1175,8 +1171,8 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
int ret, band;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
|
||||
__func__, f->tuner, f->type, f->frequency);
|
||||
dev_dbg(&s->udev->dev, "tuner=%d type=%d frequency=%u\n",
|
||||
f->tuner, f->type, f->frequency);
|
||||
|
||||
/* ADC band midpoints */
|
||||
#define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2)
|
||||
@ -1194,15 +1190,13 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
|
||||
bands_adc[band].rangelow,
|
||||
bands_adc[band].rangehigh);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
|
||||
__func__, s->f_adc);
|
||||
dev_dbg(&s->udev->dev, "ADC frequency=%u Hz\n", s->f_adc);
|
||||
ret = rtl2832_sdr_set_adc(s);
|
||||
} else if (f->tuner == 1) {
|
||||
s->f_tuner = clamp_t(unsigned int, f->frequency,
|
||||
bands_fm[0].rangelow,
|
||||
bands_fm[0].rangehigh);
|
||||
dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
|
||||
__func__, f->frequency);
|
||||
dev_dbg(&s->udev->dev, "RF frequency=%u Hz\n", f->frequency);
|
||||
|
||||
ret = rtl2832_sdr_set_tuner_freq(s);
|
||||
} else {
|
||||
@ -1217,7 +1211,7 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
|
||||
{
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
if (f->index >= s->num_formats)
|
||||
return -EINVAL;
|
||||
@ -1233,7 +1227,7 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
|
||||
{
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->udev->dev, "\n");
|
||||
|
||||
f->fmt.sdr.pixelformat = s->pixelformat;
|
||||
f->fmt.sdr.buffersize = s->buffersize;
|
||||
@ -1250,7 +1244,7 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
|
||||
struct vb2_queue *q = &s->vb_queue;
|
||||
int i;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
|
||||
dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n",
|
||||
(char *)&f->fmt.sdr.pixelformat);
|
||||
|
||||
if (vb2_is_busy(q))
|
||||
@ -1280,7 +1274,7 @@ static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
|
||||
struct rtl2832_sdr_state *s = video_drvdata(file);
|
||||
int i;
|
||||
|
||||
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
|
||||
dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n",
|
||||
(char *)&f->fmt.sdr.pixelformat);
|
||||
|
||||
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
|
||||
@ -1354,8 +1348,8 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
int ret;
|
||||
|
||||
dev_dbg(&s->udev->dev,
|
||||
"%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
|
||||
__func__, ctrl->id, ctrl->name, ctrl->val,
|
||||
"id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
|
||||
ctrl->id, ctrl->name, ctrl->val,
|
||||
ctrl->minimum, ctrl->maximum, ctrl->step);
|
||||
|
||||
switch (ctrl->id) {
|
||||
@ -1432,7 +1426,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
|
||||
s->pixelformat = formats[0].pixelformat;
|
||||
s->buffersize = formats[0].buffersize;
|
||||
s->num_formats = NUM_FORMATS;
|
||||
if (rtl2832_sdr_emulated_fmt == false)
|
||||
if (!rtl2832_sdr_emulated_fmt)
|
||||
s->num_formats -= 1;
|
||||
|
||||
mutex_init(&s->v4l2_lock);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
|
||||
Driver for Silicon Labs Si2161 DVB-T and Si2165 DVB-C/-T Demodulator
|
||||
|
||||
Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org>
|
||||
|
||||
@ -44,9 +44,7 @@ struct si2165_state {
|
||||
|
||||
struct si2165_config config;
|
||||
|
||||
/* chip revision */
|
||||
u8 revcode;
|
||||
/* chip type */
|
||||
u8 chip_revcode;
|
||||
u8 chip_type;
|
||||
|
||||
/* calculated by xtal and div settings */
|
||||
@ -312,7 +310,7 @@ static u32 si2165_get_fe_clk(struct si2165_state *state)
|
||||
return state->adc_clk;
|
||||
}
|
||||
|
||||
static bool si2165_wait_init_done(struct si2165_state *state)
|
||||
static int si2165_wait_init_done(struct si2165_state *state)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
u8 val = 0;
|
||||
@ -407,7 +405,7 @@ static int si2165_upload_firmware(struct si2165_state *state)
|
||||
int ret;
|
||||
|
||||
const struct firmware *fw = NULL;
|
||||
u8 *fw_file = SI2165_FIRMWARE;
|
||||
u8 *fw_file;
|
||||
const u8 *data;
|
||||
u32 len;
|
||||
u32 offset;
|
||||
@ -415,10 +413,20 @@ static int si2165_upload_firmware(struct si2165_state *state)
|
||||
u8 block_count;
|
||||
u16 crc_expected;
|
||||
|
||||
switch (state->chip_revcode) {
|
||||
case 0x03: /* revision D */
|
||||
fw_file = SI2165_FIRMWARE_REV_D;
|
||||
break;
|
||||
default:
|
||||
dev_info(&state->i2c->dev, "%s: no firmware file for revision=%d\n",
|
||||
KBUILD_MODNAME, state->chip_revcode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* request the firmware, this will block and timeout */
|
||||
ret = request_firmware(&fw, fw_file, state->i2c->dev.parent);
|
||||
if (ret) {
|
||||
dev_warn(&state->i2c->dev, "%s: firmare file '%s' not found\n",
|
||||
dev_warn(&state->i2c->dev, "%s: firmware file '%s' not found\n",
|
||||
KBUILD_MODNAME, fw_file);
|
||||
goto error;
|
||||
}
|
||||
@ -908,7 +916,7 @@ static void si2165_release(struct dvb_frontend *fe)
|
||||
|
||||
static struct dvb_frontend_ops si2165_ops = {
|
||||
.info = {
|
||||
.name = "Silicon Labs Si2165",
|
||||
.name = "Silicon Labs ",
|
||||
.caps = FE_CAN_FEC_1_2 |
|
||||
FE_CAN_FEC_2_3 |
|
||||
FE_CAN_FEC_3_4 |
|
||||
@ -948,6 +956,8 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config,
|
||||
int n;
|
||||
int io_ret;
|
||||
u8 val;
|
||||
char rev_char;
|
||||
const char *chip_name;
|
||||
|
||||
if (config == NULL || i2c == NULL)
|
||||
goto error;
|
||||
@ -984,7 +994,7 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config,
|
||||
if (val != state->config.chip_mode)
|
||||
goto error;
|
||||
|
||||
io_ret = si2165_readreg8(state, 0x0023 , &state->revcode);
|
||||
io_ret = si2165_readreg8(state, 0x0023, &state->chip_revcode);
|
||||
if (io_ret < 0)
|
||||
goto error;
|
||||
|
||||
@ -997,22 +1007,35 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config,
|
||||
if (io_ret < 0)
|
||||
goto error;
|
||||
|
||||
dev_info(&state->i2c->dev, "%s: hardware revision 0x%02x, chip type 0x%02x\n",
|
||||
KBUILD_MODNAME, state->revcode, state->chip_type);
|
||||
if (state->chip_revcode < 26)
|
||||
rev_char = 'A' + state->chip_revcode;
|
||||
else
|
||||
rev_char = '?';
|
||||
|
||||
/* It is a guess that register 0x0118 (chip type?) can be used to
|
||||
* differ between si2161, si2163 and si2165
|
||||
* Only si2165 has been tested.
|
||||
*/
|
||||
if (state->revcode == 0x03 && state->chip_type == 0x07) {
|
||||
switch (state->chip_type) {
|
||||
case 0x06:
|
||||
chip_name = "Si2161";
|
||||
state->has_dvbt = true;
|
||||
break;
|
||||
case 0x07:
|
||||
chip_name = "Si2165";
|
||||
state->has_dvbt = true;
|
||||
state->has_dvbc = true;
|
||||
} else {
|
||||
dev_err(&state->i2c->dev, "%s: Unsupported chip.\n",
|
||||
KBUILD_MODNAME);
|
||||
break;
|
||||
default:
|
||||
dev_err(&state->i2c->dev, "%s: Unsupported Silicon Labs chip (type %d, rev %d)\n",
|
||||
KBUILD_MODNAME, state->chip_type, state->chip_revcode);
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev_info(&state->i2c->dev,
|
||||
"%s: Detected Silicon Labs %s-%c (type %d, rev %d)\n",
|
||||
KBUILD_MODNAME, chip_name, rev_char, state->chip_type,
|
||||
state->chip_revcode);
|
||||
|
||||
strlcat(state->frontend.ops.info.name, chip_name,
|
||||
sizeof(state->frontend.ops.info.name));
|
||||
|
||||
n = 0;
|
||||
if (state->has_dvbt) {
|
||||
state->frontend.ops.delsys[n++] = SYS_DVBT;
|
||||
@ -1037,4 +1060,4 @@ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
|
||||
MODULE_DESCRIPTION("Silicon Labs Si2165 DVB-C/-T Demodulator driver");
|
||||
MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE(SI2165_FIRMWARE);
|
||||
MODULE_FIRMWARE(SI2165_FIRMWARE_REV_D);
|
||||
|
@ -18,6 +18,6 @@
|
||||
#ifndef _DVB_SI2165_PRIV
|
||||
#define _DVB_SI2165_PRIV
|
||||
|
||||
#define SI2165_FIRMWARE "dvb-demod-si2165.fw"
|
||||
#define SI2165_FIRMWARE_REV_D "dvb-demod-si2165.fw"
|
||||
|
||||
#endif /* _DVB_SI2165_PRIV */
|
||||
|
@ -55,8 +55,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n",
|
||||
__func__,
|
||||
dev_dbg(&s->client->dev, "cmd execution took %d ms\n",
|
||||
jiffies_to_msecs(jiffies) -
|
||||
(jiffies_to_msecs(timeout) - TIMEOUT));
|
||||
|
||||
@ -75,7 +74,7 @@ err_mutex_unlock:
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -150,12 +149,12 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n",
|
||||
__func__, *status, cmd.rlen, cmd.args);
|
||||
dev_dbg(&s->client->dev, "status=%02x args=%*ph\n",
|
||||
*status, cmd.rlen, cmd.args);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -168,10 +167,10 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||
u8 bandwidth, delivery_system;
|
||||
|
||||
dev_dbg(&s->client->dev,
|
||||
"%s: delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u\n",
|
||||
__func__, c->delivery_system, c->modulation,
|
||||
"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n",
|
||||
c->delivery_system, c->modulation,
|
||||
c->frequency, c->bandwidth_hz, c->symbol_rate,
|
||||
c->inversion);
|
||||
c->inversion, c->stream_id);
|
||||
|
||||
if (!s->active) {
|
||||
ret = -EAGAIN;
|
||||
@ -235,6 +234,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (c->delivery_system == SYS_DVBT2) {
|
||||
/* select PLP */
|
||||
cmd.args[0] = 0x52;
|
||||
cmd.args[1] = c->stream_id & 0xff;
|
||||
cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1;
|
||||
cmd.wlen = 3;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(cmd.args, "\x51\x03", 2);
|
||||
cmd.wlen = 2;
|
||||
cmd.rlen = 12;
|
||||
@ -297,13 +308,6 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
@ -343,7 +347,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -357,8 +361,9 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
struct si2168_cmd cmd;
|
||||
unsigned int chip_id;
|
||||
|
||||
dev_dbg(&s->client->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->client->dev, "\n");
|
||||
|
||||
/* initialize */
|
||||
memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
|
||||
cmd.wlen = 13;
|
||||
cmd.rlen = 0;
|
||||
@ -366,6 +371,26 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (s->fw_loaded) {
|
||||
/* resume */
|
||||
memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8);
|
||||
cmd.wlen = 8;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x85", 1);
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
goto warm;
|
||||
}
|
||||
|
||||
/* power up */
|
||||
memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
|
||||
cmd.wlen = 8;
|
||||
cmd.rlen = 1;
|
||||
@ -400,16 +425,16 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
break;
|
||||
default:
|
||||
dev_err(&s->client->dev,
|
||||
"%s: unkown chip version Si21%d-%c%c%c\n",
|
||||
KBUILD_MODNAME, cmd.args[2], cmd.args[1],
|
||||
"unknown chip version Si21%d-%c%c%c\n",
|
||||
cmd.args[2], cmd.args[1],
|
||||
cmd.args[3], cmd.args[4]);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* cold state - try to download firmware */
|
||||
dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
|
||||
KBUILD_MODNAME, si2168_ops.info.name);
|
||||
dev_info(&s->client->dev, "found a '%s' in cold state\n",
|
||||
si2168_ops.info.name);
|
||||
|
||||
/* request the firmware, this will block and timeout */
|
||||
ret = request_firmware(&fw, fw_file, &s->client->dev);
|
||||
@ -422,18 +447,18 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
|
||||
if (ret == 0) {
|
||||
dev_notice(&s->client->dev,
|
||||
"%s: please install firmware file '%s'\n",
|
||||
KBUILD_MODNAME, SI2168_B40_FIRMWARE);
|
||||
"please install firmware file '%s'\n",
|
||||
SI2168_B40_FIRMWARE);
|
||||
} else {
|
||||
dev_err(&s->client->dev,
|
||||
"%s: firmware file '%s' not found\n",
|
||||
KBUILD_MODNAME, fw_file);
|
||||
"firmware file '%s' not found\n",
|
||||
fw_file);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
|
||||
KBUILD_MODNAME, fw_file);
|
||||
dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
|
||||
fw_file);
|
||||
|
||||
for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
|
||||
len = remaining;
|
||||
@ -446,8 +471,8 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret) {
|
||||
dev_err(&s->client->dev,
|
||||
"%s: firmware download failed=%d\n",
|
||||
KBUILD_MODNAME, ret);
|
||||
"firmware download failed=%d\n",
|
||||
ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@ -462,8 +487,20 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
dev_info(&s->client->dev, "%s: found a '%s' in warm state\n",
|
||||
KBUILD_MODNAME, si2168_ops.info.name);
|
||||
/* set ts mode */
|
||||
memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
|
||||
cmd.args[4] |= s->ts_mode;
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
s->fw_loaded = true;
|
||||
|
||||
warm:
|
||||
dev_info(&s->client->dev, "found a '%s' in warm state\n",
|
||||
si2168_ops.info.name);
|
||||
|
||||
s->active = true;
|
||||
|
||||
@ -472,7 +509,7 @@ err:
|
||||
if (fw)
|
||||
release_firmware(fw);
|
||||
|
||||
dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -482,7 +519,7 @@ static int si2168_sleep(struct dvb_frontend *fe)
|
||||
int ret;
|
||||
struct si2168_cmd cmd;
|
||||
|
||||
dev_dbg(&s->client->dev, "%s:\n", __func__);
|
||||
dev_dbg(&s->client->dev, "\n");
|
||||
|
||||
s->active = false;
|
||||
|
||||
@ -495,7 +532,7 @@ static int si2168_sleep(struct dvb_frontend *fe)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -528,8 +565,7 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
|
||||
/* open tuner I2C gate */
|
||||
ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1);
|
||||
if (ret != 1) {
|
||||
dev_warn(&s->client->dev, "%s: i2c write failed=%d\n",
|
||||
KBUILD_MODNAME, ret);
|
||||
dev_warn(&s->client->dev, "i2c write failed=%d\n", ret);
|
||||
if (ret >= 0)
|
||||
ret = -EREMOTEIO;
|
||||
} else {
|
||||
@ -553,8 +589,7 @@ static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
|
||||
/* close tuner I2C gate */
|
||||
ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1);
|
||||
if (ret != 1) {
|
||||
dev_warn(&s->client->dev, "%s: i2c write failed=%d\n",
|
||||
KBUILD_MODNAME, ret);
|
||||
dev_warn(&s->client->dev, "i2c write failed=%d\n", ret);
|
||||
if (ret >= 0)
|
||||
ret = -EREMOTEIO;
|
||||
} else {
|
||||
@ -587,7 +622,8 @@ static const struct dvb_frontend_ops si2168_ops = {
|
||||
FE_CAN_GUARD_INTERVAL_AUTO |
|
||||
FE_CAN_HIERARCHY_AUTO |
|
||||
FE_CAN_MUTE_TS |
|
||||
FE_CAN_2G_MODULATION
|
||||
FE_CAN_2G_MODULATION |
|
||||
FE_CAN_MULTISTREAM
|
||||
},
|
||||
|
||||
.get_tune_settings = si2168_get_tune_settings,
|
||||
@ -607,12 +643,12 @@ static int si2168_probe(struct i2c_client *client,
|
||||
struct si2168 *s;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&client->dev, "%s:\n", __func__);
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
s = kzalloc(sizeof(struct si2168), GFP_KERNEL);
|
||||
if (!s) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
|
||||
dev_err(&client->dev, "kzalloc() failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -633,16 +669,17 @@ static int si2168_probe(struct i2c_client *client,
|
||||
|
||||
*config->i2c_adapter = s->adapter;
|
||||
*config->fe = &s->fe;
|
||||
s->ts_mode = config->ts_mode;
|
||||
s->fw_loaded = false;
|
||||
|
||||
i2c_set_clientdata(client, s);
|
||||
|
||||
dev_info(&s->client->dev,
|
||||
"%s: Silicon Labs Si2168 successfully attached\n",
|
||||
KBUILD_MODNAME);
|
||||
"Silicon Labs Si2168 successfully attached\n");
|
||||
return 0;
|
||||
err:
|
||||
kfree(s);
|
||||
dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
|
||||
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -650,7 +687,7 @@ static int si2168_remove(struct i2c_client *client)
|
||||
{
|
||||
struct si2168 *s = i2c_get_clientdata(client);
|
||||
|
||||
dev_dbg(&client->dev, "%s:\n", __func__);
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
i2c_del_mux_adapter(s->adapter);
|
||||
|
||||
|
@ -34,6 +34,12 @@ struct si2168_config {
|
||||
* returned by driver
|
||||
*/
|
||||
struct i2c_adapter **i2c_adapter;
|
||||
|
||||
/* TS mode */
|
||||
u8 ts_mode;
|
||||
};
|
||||
|
||||
#define SI2168_TS_PARALLEL 0x06
|
||||
#define SI2168_TS_SERIAL 0x03
|
||||
|
||||
#endif
|
||||
|
@ -36,6 +36,8 @@ struct si2168 {
|
||||
fe_delivery_system_t delivery_system;
|
||||
fe_status_t fe_status;
|
||||
bool active;
|
||||
bool fw_loaded;
|
||||
u8 ts_mode;
|
||||
};
|
||||
|
||||
/* firmare command struct */
|
||||
|
@ -236,6 +236,9 @@ static int si21_writeregs(struct si21xx_state *state, u8 reg1,
|
||||
.len = len + 1
|
||||
};
|
||||
|
||||
if (len > sizeof(buf) - 1)
|
||||
return -EINVAL;
|
||||
|
||||
msg.buf[0] = reg1;
|
||||
memcpy(msg.buf + 1, data, len);
|
||||
|
||||
|
441
drivers/media/dvb-frontends/sp2.c
Normal file
441
drivers/media/dvb-frontends/sp2.c
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* CIMaX SP2/SP2HF (Atmel T90FJR) CI driver
|
||||
*
|
||||
* Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi>
|
||||
*
|
||||
* Heavily based on CIMax2(R) SP2 driver in conjunction with NetUp Dual
|
||||
* DVB-S2 CI card (cimax2) with following copyrights:
|
||||
*
|
||||
* Copyright (C) 2009 NetUP Inc.
|
||||
* Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
|
||||
* Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "sp2_priv.h"
|
||||
|
||||
static int sp2_read_i2c(struct sp2 *s, u8 reg, u8 *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_client *client = s->client;
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct i2c_msg msg[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.buf = ®,
|
||||
.len = 1
|
||||
}, {
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.buf = buf,
|
||||
.len = len
|
||||
}
|
||||
};
|
||||
|
||||
ret = i2c_transfer(adap, msg, 2);
|
||||
|
||||
if (ret != 2) {
|
||||
dev_err(&client->dev, "i2c read error, reg = 0x%02x, status = %d\n",
|
||||
reg, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %02x\n",
|
||||
client->addr, reg, buf[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp2_write_i2c(struct sp2 *s, u8 reg, u8 *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
u8 buffer[35];
|
||||
struct i2c_client *client = s->client;
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct i2c_msg msg = {
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.buf = &buffer[0],
|
||||
.len = len + 1
|
||||
};
|
||||
|
||||
if ((len + 1) > sizeof(buffer)) {
|
||||
dev_err(&client->dev, "i2c wr reg=%02x: len=%d is too big!\n",
|
||||
reg, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buffer[0] = reg;
|
||||
memcpy(&buffer[1], buf, len);
|
||||
|
||||
ret = i2c_transfer(adap, &msg, 1);
|
||||
|
||||
if (ret != 1) {
|
||||
dev_err(&client->dev, "i2c write error, reg = 0x%02x, status = %d\n",
|
||||
reg, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp2_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, u8 acs,
|
||||
u8 read, int addr, u8 data)
|
||||
{
|
||||
struct sp2 *s = en50221->data;
|
||||
u8 store;
|
||||
int mem, ret;
|
||||
int (*ci_op_cam)(void*, u8, int, u8, int*) = s->ci_control;
|
||||
|
||||
dev_dbg(&s->client->dev, "slot=%d, acs=0x%02x, addr=0x%04x, data = 0x%02x",
|
||||
slot, acs, addr, data);
|
||||
|
||||
if (slot != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* change module access type between IO space and attribute memory
|
||||
* when needed
|
||||
*/
|
||||
if (s->module_access_type != acs) {
|
||||
ret = sp2_read_i2c(s, 0x00, &store, 1);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
store &= ~(SP2_MOD_CTL_ACS1 | SP2_MOD_CTL_ACS0);
|
||||
store |= acs;
|
||||
|
||||
ret = sp2_write_i2c(s, 0x00, &store, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->module_access_type = acs;
|
||||
|
||||
/* implementation of ci_op_cam is device specific */
|
||||
if (ci_op_cam) {
|
||||
ret = ci_op_cam(s->priv, read, addr, data, &mem);
|
||||
} else {
|
||||
dev_err(&s->client->dev, "callback not defined");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (read) {
|
||||
dev_dbg(&s->client->dev, "cam read, addr=0x%04x, data = 0x%04x",
|
||||
addr, mem);
|
||||
return mem;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
|
||||
int slot, int addr)
|
||||
{
|
||||
return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS,
|
||||
SP2_CI_RD, addr, 0);
|
||||
}
|
||||
|
||||
int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
|
||||
int slot, int addr, u8 data)
|
||||
{
|
||||
return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS,
|
||||
SP2_CI_WR, addr, data);
|
||||
}
|
||||
|
||||
int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221,
|
||||
int slot, u8 addr)
|
||||
{
|
||||
return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS,
|
||||
SP2_CI_RD, addr, 0);
|
||||
}
|
||||
|
||||
int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221,
|
||||
int slot, u8 addr, u8 data)
|
||||
{
|
||||
return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS,
|
||||
SP2_CI_WR, addr, data);
|
||||
}
|
||||
|
||||
int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
|
||||
{
|
||||
struct sp2 *s = en50221->data;
|
||||
u8 buf;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&s->client->dev, "slot: %d\n", slot);
|
||||
|
||||
if (slot != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* RST on */
|
||||
buf = SP2_MOD_CTL_RST;
|
||||
ret = sp2_write_i2c(s, 0x00, &buf, 1);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
usleep_range(500, 600);
|
||||
|
||||
/* RST off */
|
||||
buf = 0x00;
|
||||
ret = sp2_write_i2c(s, 0x00, &buf, 1);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
msleep(1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
|
||||
{
|
||||
struct sp2 *s = en50221->data;
|
||||
|
||||
dev_dbg(&s->client->dev, "slot:%d\n", slot);
|
||||
|
||||
/* not implemented */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot)
|
||||
{
|
||||
struct sp2 *s = en50221->data;
|
||||
u8 buf;
|
||||
|
||||
dev_dbg(&s->client->dev, "slot:%d\n", slot);
|
||||
|
||||
if (slot != 0)
|
||||
return -EINVAL;
|
||||
|
||||
sp2_read_i2c(s, 0x00, &buf, 1);
|
||||
|
||||
/* disable bypass and enable TS */
|
||||
buf |= (SP2_MOD_CTL_TSOEN | SP2_MOD_CTL_TSIEN);
|
||||
return sp2_write_i2c(s, 0, &buf, 1);
|
||||
}
|
||||
|
||||
int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221,
|
||||
int slot, int open)
|
||||
{
|
||||
struct sp2 *s = en50221->data;
|
||||
u8 buf[2];
|
||||
int ret;
|
||||
|
||||
dev_dbg(&s->client->dev, "slot:%d open:%d\n", slot, open);
|
||||
|
||||
/*
|
||||
* CAM module INSERT/REMOVE processing. Slow operation because of i2c
|
||||
* transfers. Throttle read to one per sec.
|
||||
*/
|
||||
if (time_after(jiffies, s->next_status_checked_time)) {
|
||||
ret = sp2_read_i2c(s, 0x00, buf, 1);
|
||||
s->next_status_checked_time = jiffies + msecs_to_jiffies(1000);
|
||||
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
if (buf[0] & SP2_MOD_CTL_DET)
|
||||
s->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
|
||||
DVB_CA_EN50221_POLL_CAM_READY;
|
||||
else
|
||||
s->status = 0;
|
||||
}
|
||||
|
||||
return s->status;
|
||||
}
|
||||
|
||||
int sp2_init(struct sp2 *s)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 buf;
|
||||
u8 cimax_init[34] = {
|
||||
0x00, /* module A control*/
|
||||
0x00, /* auto select mask high A */
|
||||
0x00, /* auto select mask low A */
|
||||
0x00, /* auto select pattern high A */
|
||||
0x00, /* auto select pattern low A */
|
||||
0x44, /* memory access time A, 600 ns */
|
||||
0x00, /* invert input A */
|
||||
0x00, /* RFU */
|
||||
0x00, /* RFU */
|
||||
0x00, /* module B control*/
|
||||
0x00, /* auto select mask high B */
|
||||
0x00, /* auto select mask low B */
|
||||
0x00, /* auto select pattern high B */
|
||||
0x00, /* auto select pattern low B */
|
||||
0x44, /* memory access time B, 600 ns */
|
||||
0x00, /* invert input B */
|
||||
0x00, /* RFU */
|
||||
0x00, /* RFU */
|
||||
0x00, /* auto select mask high Ext */
|
||||
0x00, /* auto select mask low Ext */
|
||||
0x00, /* auto select pattern high Ext */
|
||||
0x00, /* auto select pattern low Ext */
|
||||
0x00, /* RFU */
|
||||
0x02, /* destination - module A */
|
||||
0x01, /* power control reg, VCC power on */
|
||||
0x00, /* RFU */
|
||||
0x00, /* int status read only */
|
||||
0x00, /* Interrupt Mask Register */
|
||||
0x05, /* EXTINT=active-high, INT=push-pull */
|
||||
0x00, /* USCG1 */
|
||||
0x04, /* ack active low */
|
||||
0x00, /* LOCK = 0 */
|
||||
0x22, /* unknown */
|
||||
0x00, /* synchronization? */
|
||||
};
|
||||
|
||||
dev_dbg(&s->client->dev, "\n");
|
||||
|
||||
s->ca.owner = THIS_MODULE;
|
||||
s->ca.read_attribute_mem = sp2_ci_read_attribute_mem;
|
||||
s->ca.write_attribute_mem = sp2_ci_write_attribute_mem;
|
||||
s->ca.read_cam_control = sp2_ci_read_cam_control;
|
||||
s->ca.write_cam_control = sp2_ci_write_cam_control;
|
||||
s->ca.slot_reset = sp2_ci_slot_reset;
|
||||
s->ca.slot_shutdown = sp2_ci_slot_shutdown;
|
||||
s->ca.slot_ts_enable = sp2_ci_slot_ts_enable;
|
||||
s->ca.poll_slot_status = sp2_ci_poll_slot_status;
|
||||
s->ca.data = s;
|
||||
s->module_access_type = 0;
|
||||
|
||||
/* initialize all regs */
|
||||
ret = sp2_write_i2c(s, 0x00, &cimax_init[0], 34);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* lock registers */
|
||||
buf = 1;
|
||||
ret = sp2_write_i2c(s, 0x1f, &buf, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* power on slots */
|
||||
ret = sp2_write_i2c(s, 0x18, &buf, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = dvb_ca_en50221_init(s->dvb_adap, &s->ca, 0, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "init failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sp2_exit(struct i2c_client *client)
|
||||
{
|
||||
struct sp2 *s;
|
||||
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
if (client == NULL)
|
||||
return 0;
|
||||
|
||||
s = i2c_get_clientdata(client);
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
|
||||
if (s->ca.data == NULL)
|
||||
return 0;
|
||||
|
||||
dvb_ca_en50221_release(&s->ca);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp2_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct sp2_config *cfg = client->dev.platform_data;
|
||||
struct sp2 *s;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
s = kzalloc(sizeof(struct sp2), GFP_KERNEL);
|
||||
if (!s) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&client->dev, "kzalloc() failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->client = client;
|
||||
s->dvb_adap = cfg->dvb_adap;
|
||||
s->priv = cfg->priv;
|
||||
s->ci_control = cfg->ci_control;
|
||||
|
||||
i2c_set_clientdata(client, s);
|
||||
|
||||
ret = sp2_init(s);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
dev_info(&s->client->dev, "CIMaX SP2 successfully attached\n");
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&client->dev, "init failed=%d\n", ret);
|
||||
kfree(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sp2_remove(struct i2c_client *client)
|
||||
{
|
||||
struct si2157 *s = i2c_get_clientdata(client);
|
||||
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
sp2_exit(client);
|
||||
if (s != NULL)
|
||||
kfree(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id sp2_id[] = {
|
||||
{"sp2", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, sp2_id);
|
||||
|
||||
static struct i2c_driver sp2_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "sp2",
|
||||
},
|
||||
.probe = sp2_probe,
|
||||
.remove = sp2_remove,
|
||||
.id_table = sp2_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(sp2_driver);
|
||||
|
||||
MODULE_DESCRIPTION("CIMaX SP2/HF CI driver");
|
||||
MODULE_AUTHOR("Olli Salonen <olli.salonen@iki.fi>");
|
||||
MODULE_LICENSE("GPL");
|
53
drivers/media/dvb-frontends/sp2.h
Normal file
53
drivers/media/dvb-frontends/sp2.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* CIMaX SP2/HF CI driver
|
||||
*
|
||||
* Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SP2_H
|
||||
#define SP2_H
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include "dvb_ca_en50221.h"
|
||||
|
||||
/*
|
||||
* I2C address
|
||||
* 0x40 (port 0)
|
||||
* 0x41 (port 1)
|
||||
*/
|
||||
struct sp2_config {
|
||||
/* dvb_adapter to attach the ci to */
|
||||
struct dvb_adapter *dvb_adap;
|
||||
|
||||
/* function ci_control handles the device specific ci ops */
|
||||
void *ci_control;
|
||||
|
||||
/* priv is passed back to function ci_control */
|
||||
void *priv;
|
||||
};
|
||||
|
||||
extern int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
|
||||
int slot, int addr);
|
||||
extern int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
|
||||
int slot, int addr, u8 data);
|
||||
extern int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221,
|
||||
int slot, u8 addr);
|
||||
extern int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221,
|
||||
int slot, u8 addr, u8 data);
|
||||
extern int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot);
|
||||
extern int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot);
|
||||
extern int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot);
|
||||
extern int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221,
|
||||
int slot, int open);
|
||||
|
||||
#endif
|
50
drivers/media/dvb-frontends/sp2_priv.h
Normal file
50
drivers/media/dvb-frontends/sp2_priv.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* CIMaX SP2/HF CI driver
|
||||
*
|
||||
* Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SP2_PRIV_H
|
||||
#define SP2_PRIV_H
|
||||
|
||||
#include "sp2.h"
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
/* state struct */
|
||||
struct sp2 {
|
||||
int status;
|
||||
struct i2c_client *client;
|
||||
struct dvb_adapter *dvb_adap;
|
||||
struct dvb_ca_en50221 ca;
|
||||
int module_access_type;
|
||||
unsigned long next_status_checked_time;
|
||||
void *priv;
|
||||
void *ci_control;
|
||||
};
|
||||
|
||||
#define SP2_CI_ATTR_ACS 0x00
|
||||
#define SP2_CI_IO_ACS 0x04
|
||||
#define SP2_CI_WR 0
|
||||
#define SP2_CI_RD 1
|
||||
|
||||
/* Module control register (0x00 module A, 0x09 module B) bits */
|
||||
#define SP2_MOD_CTL_DET 0x01
|
||||
#define SP2_MOD_CTL_AUTO 0x02
|
||||
#define SP2_MOD_CTL_ACS0 0x04
|
||||
#define SP2_MOD_CTL_ACS1 0x08
|
||||
#define SP2_MOD_CTL_HAD 0x10
|
||||
#define SP2_MOD_CTL_TSIEN 0x20
|
||||
#define SP2_MOD_CTL_TSOEN 0x40
|
||||
#define SP2_MOD_CTL_RST 0x80
|
||||
|
||||
#endif
|
@ -394,8 +394,7 @@ static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
|
||||
tmp = ret << 6;
|
||||
|
||||
tmp = ret << 6;
|
||||
if (tmp >= 0x3FFF0)
|
||||
tmp = ~0;
|
||||
|
||||
|
@ -59,7 +59,6 @@ struct stv0367cab_state {
|
||||
int locked; /* channel found */
|
||||
u32 freq_khz; /* found frequency (in kHz) */
|
||||
u32 symbol_rate; /* found symbol rate (in Bds) */
|
||||
enum stv0367cab_mod modulation; /* modulation */
|
||||
fe_spectral_inversion_t spect_inv; /* Spectrum Inversion */
|
||||
};
|
||||
|
||||
@ -554,7 +553,7 @@ static struct st_register def0367ter[STV0367TER_NBREGS] = {
|
||||
#define RF_LOOKUP_TABLE_SIZE 31
|
||||
#define RF_LOOKUP_TABLE2_SIZE 16
|
||||
/* RF Level (for RF AGC->AGC1) Lookup Table, depends on the board and tuner.*/
|
||||
s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = {
|
||||
static const s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = {
|
||||
{/*AGC1*/
|
||||
48, 50, 51, 53, 54, 56, 57, 58, 60, 61, 62, 63,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
|
||||
@ -566,7 +565,7 @@ s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = {
|
||||
}
|
||||
};
|
||||
/* RF Level (for IF AGC->AGC2) Lookup Table, depends on the board and tuner.*/
|
||||
s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = {
|
||||
static const s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = {
|
||||
{/*AGC2*/
|
||||
28, 29, 31, 32, 34, 35, 36, 37,
|
||||
38, 39, 40, 41, 42, 43, 44, 45,
|
||||
@ -1935,8 +1934,6 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe)
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
struct stv0367_state *state = fe->demodulator_priv;
|
||||
struct stv0367ter_state *ter_state = state->ter_state;
|
||||
|
||||
int error = 0;
|
||||
enum stv0367_ter_mode mode;
|
||||
int constell = 0,/* snr = 0,*/ Data = 0;
|
||||
|
||||
@ -2020,7 +2017,7 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe)
|
||||
|
||||
p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD);
|
||||
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
@ -2999,7 +2996,6 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
|
||||
|
||||
if (QAMFEC_Lock) {
|
||||
signalType = FE_CAB_DATAOK;
|
||||
cab_state->modulation = p->modulation;
|
||||
cab_state->spect_inv = stv0367_readbits(state,
|
||||
F367CAB_QUAD_INV);
|
||||
#if 0
|
||||
@ -3165,7 +3161,7 @@ static int stv0367cab_get_frontend(struct dvb_frontend *fe)
|
||||
case FE_CAB_MOD_QAM128:
|
||||
p->modulation = QAM_128;
|
||||
break;
|
||||
case QAM_256:
|
||||
case FE_CAB_MOD_QAM256:
|
||||
p->modulation = QAM_256;
|
||||
break;
|
||||
default:
|
||||
|
@ -1270,7 +1270,6 @@ enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp,
|
||||
enum fe_stv0900_demod_mode LDPC_Mode,
|
||||
enum fe_stv0900_demod_num demod)
|
||||
{
|
||||
enum fe_stv0900_error error = STV0900_NO_ERROR;
|
||||
s32 reg_ind;
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
@ -1337,7 +1336,7 @@ enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp,
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
return STV0900_NO_ERROR;
|
||||
}
|
||||
|
||||
static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
|
||||
@ -1555,8 +1554,6 @@ static int stv0900_status(struct stv0900_internal *intp,
|
||||
static int stv0900_set_mis(struct stv0900_internal *intp,
|
||||
enum fe_stv0900_demod_num demod, int mis)
|
||||
{
|
||||
enum fe_stv0900_error error = STV0900_NO_ERROR;
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
if (mis < 0 || mis > 255) {
|
||||
@ -1569,7 +1566,7 @@ static int stv0900_set_mis(struct stv0900_internal *intp,
|
||||
stv0900_write_reg(intp, ISIBITENA, 0xff);
|
||||
}
|
||||
|
||||
return error;
|
||||
return STV0900_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1733,9 +1733,10 @@ static void stv0900_set_search_standard(struct stv0900_internal *intp,
|
||||
break;
|
||||
case STV0900_SEARCH_DSS:
|
||||
dprintk("Search Standard = DSS\n");
|
||||
case STV0900_SEARCH_DVBS2:
|
||||
break;
|
||||
case STV0900_SEARCH_DVBS2:
|
||||
dprintk("Search Standard = DVBS2\n");
|
||||
break;
|
||||
case STV0900_AUTO_SEARCH:
|
||||
default:
|
||||
dprintk("Search Standard = AUTO\n");
|
||||
|
840
drivers/media/dvb-frontends/tc90522.c
Normal file
840
drivers/media/dvb-frontends/tc90522.c
Normal file
@ -0,0 +1,840 @@
|
||||
/*
|
||||
* Toshiba TC90522 Demodulator
|
||||
*
|
||||
* Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation version 2.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTICE:
|
||||
* This driver is incomplete and lacks init/config of the chips,
|
||||
* as the necessary info is not disclosed.
|
||||
* It assumes that users of this driver (such as a PCI bridge of
|
||||
* DTV receiver cards) properly init and configure the chip
|
||||
* via I2C *before* calling this driver's init() function.
|
||||
*
|
||||
* Currently, PT3 driver is the only one that uses this driver,
|
||||
* and contains init/config code in its firmware.
|
||||
* Thus some part of the code might be dependent on PT3 specific config.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include "dvb_math.h"
|
||||
#include "tc90522.h"
|
||||
|
||||
#define TC90522_I2C_THRU_REG 0xfe
|
||||
|
||||
#define TC90522_MODULE_IDX(addr) (((u8)(addr) & 0x02U) >> 1)
|
||||
|
||||
struct tc90522_state {
|
||||
struct tc90522_config cfg;
|
||||
struct dvb_frontend fe;
|
||||
struct i2c_client *i2c_client;
|
||||
struct i2c_adapter tuner_i2c;
|
||||
|
||||
bool lna;
|
||||
};
|
||||
|
||||
struct reg_val {
|
||||
u8 reg;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
static int
|
||||
reg_write(struct tc90522_state *state, const struct reg_val *regs, int num)
|
||||
{
|
||||
int i, ret;
|
||||
struct i2c_msg msg;
|
||||
|
||||
ret = 0;
|
||||
msg.addr = state->i2c_client->addr;
|
||||
msg.flags = 0;
|
||||
msg.len = 2;
|
||||
for (i = 0; i < num; i++) {
|
||||
msg.buf = (u8 *)®s[i];
|
||||
ret = i2c_transfer(state->i2c_client->adapter, &msg, 1);
|
||||
if (ret == 0)
|
||||
ret = -EIO;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reg_read(struct tc90522_state *state, u8 reg, u8 *val, u8 len)
|
||||
{
|
||||
struct i2c_msg msgs[2] = {
|
||||
{
|
||||
.addr = state->i2c_client->addr,
|
||||
.flags = 0,
|
||||
.buf = ®,
|
||||
.len = 1,
|
||||
},
|
||||
{
|
||||
.addr = state->i2c_client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.buf = val,
|
||||
.len = len,
|
||||
},
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = i2c_transfer(state->i2c_client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret == ARRAY_SIZE(msgs))
|
||||
ret = 0;
|
||||
else if (ret >= 0)
|
||||
ret = -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct tc90522_state *cfg_to_state(struct tc90522_config *c)
|
||||
{
|
||||
return container_of(c, struct tc90522_state, cfg);
|
||||
}
|
||||
|
||||
|
||||
static int tc90522s_set_tsid(struct dvb_frontend *fe)
|
||||
{
|
||||
struct reg_val set_tsid[] = {
|
||||
{ 0x8f, 00 },
|
||||
{ 0x90, 00 }
|
||||
};
|
||||
|
||||
set_tsid[0].val = (fe->dtv_property_cache.stream_id & 0xff00) >> 8;
|
||||
set_tsid[1].val = fe->dtv_property_cache.stream_id & 0xff;
|
||||
return reg_write(fe->demodulator_priv, set_tsid, ARRAY_SIZE(set_tsid));
|
||||
}
|
||||
|
||||
static int tc90522t_set_layers(struct dvb_frontend *fe)
|
||||
{
|
||||
struct reg_val rv;
|
||||
u8 laysel;
|
||||
|
||||
laysel = ~fe->dtv_property_cache.isdbt_layer_enabled & 0x07;
|
||||
laysel = (laysel & 0x01) << 2 | (laysel & 0x02) | (laysel & 0x04) >> 2;
|
||||
rv.reg = 0x71;
|
||||
rv.val = laysel;
|
||||
return reg_write(fe->demodulator_priv, &rv, 1);
|
||||
}
|
||||
|
||||
/* frontend ops */
|
||||
|
||||
static int tc90522s_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
int ret;
|
||||
u8 reg;
|
||||
|
||||
state = fe->demodulator_priv;
|
||||
ret = reg_read(state, 0xc3, ®, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*status = 0;
|
||||
if (reg & 0x80) /* input level under min ? */
|
||||
return 0;
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
|
||||
if (reg & 0x60) /* carrier? */
|
||||
return 0;
|
||||
*status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC;
|
||||
|
||||
if (reg & 0x10)
|
||||
return 0;
|
||||
if (reg_read(state, 0xc5, ®, 1) < 0 || !(reg & 0x03))
|
||||
return 0;
|
||||
*status |= FE_HAS_LOCK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc90522t_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
int ret;
|
||||
u8 reg;
|
||||
|
||||
state = fe->demodulator_priv;
|
||||
ret = reg_read(state, 0x96, ®, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*status = 0;
|
||||
if (reg & 0xe0) {
|
||||
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI
|
||||
| FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = reg_read(state, 0x80, ®, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (reg & 0xf0)
|
||||
return 0;
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
|
||||
if (reg & 0x0c)
|
||||
return 0;
|
||||
*status |= FE_HAS_SYNC | FE_HAS_VITERBI;
|
||||
|
||||
if (reg & 0x02)
|
||||
return 0;
|
||||
*status |= FE_HAS_LOCK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const fe_code_rate_t fec_conv_sat[] = {
|
||||
FEC_NONE, /* unused */
|
||||
FEC_1_2, /* for BPSK */
|
||||
FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, /* for QPSK */
|
||||
FEC_2_3, /* for 8PSK. (trellis code) */
|
||||
};
|
||||
|
||||
static int tc90522s_get_frontend(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
struct dtv_frontend_properties *c;
|
||||
struct dtv_fe_stats *stats;
|
||||
int ret, i;
|
||||
int layers;
|
||||
u8 val[10];
|
||||
u32 cndat;
|
||||
|
||||
state = fe->demodulator_priv;
|
||||
c = &fe->dtv_property_cache;
|
||||
c->delivery_system = SYS_ISDBS;
|
||||
|
||||
layers = 0;
|
||||
ret = reg_read(state, 0xe8, val, 3);
|
||||
if (ret == 0) {
|
||||
int slots;
|
||||
u8 v;
|
||||
|
||||
/* high/single layer */
|
||||
v = (val[0] & 0x70) >> 4;
|
||||
c->modulation = (v == 7) ? PSK_8 : QPSK;
|
||||
c->fec_inner = fec_conv_sat[v];
|
||||
c->layer[0].fec = c->fec_inner;
|
||||
c->layer[0].modulation = c->modulation;
|
||||
c->layer[0].segment_count = val[1] & 0x3f; /* slots */
|
||||
|
||||
/* low layer */
|
||||
v = (val[0] & 0x07);
|
||||
c->layer[1].fec = fec_conv_sat[v];
|
||||
if (v == 0) /* no low layer */
|
||||
c->layer[1].segment_count = 0;
|
||||
else
|
||||
c->layer[1].segment_count = val[2] & 0x3f; /* slots */
|
||||
/* actually, BPSK if v==1, but not defined in fe_modulation_t */
|
||||
c->layer[1].modulation = QPSK;
|
||||
layers = (v > 0) ? 2 : 1;
|
||||
|
||||
slots = c->layer[0].segment_count + c->layer[1].segment_count;
|
||||
c->symbol_rate = 28860000 * slots / 48;
|
||||
}
|
||||
|
||||
/* statistics */
|
||||
|
||||
stats = &c->strength;
|
||||
stats->len = 0;
|
||||
/* let the connected tuner set RSSI property cache */
|
||||
if (fe->ops.tuner_ops.get_rf_strength) {
|
||||
u16 dummy;
|
||||
|
||||
fe->ops.tuner_ops.get_rf_strength(fe, &dummy);
|
||||
}
|
||||
|
||||
stats = &c->cnr;
|
||||
stats->len = 1;
|
||||
stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
cndat = 0;
|
||||
ret = reg_read(state, 0xbc, val, 2);
|
||||
if (ret == 0)
|
||||
cndat = val[0] << 8 | val[1];
|
||||
if (cndat >= 3000) {
|
||||
u32 p, p4;
|
||||
s64 cn;
|
||||
|
||||
cndat -= 3000; /* cndat: 4.12 fixed point float */
|
||||
/*
|
||||
* cnr[mdB] = -1634.6 * P^5 + 14341 * P^4 - 50259 * P^3
|
||||
* + 88977 * P^2 - 89565 * P + 58857
|
||||
* (P = sqrt(cndat) / 64)
|
||||
*/
|
||||
/* p := sqrt(cndat) << 8 = P << 14, 2.14 fixed point float */
|
||||
/* cn = cnr << 3 */
|
||||
p = int_sqrt(cndat << 16);
|
||||
p4 = cndat * cndat;
|
||||
cn = div64_s64(-16346LL * p4 * p, 10) >> 35;
|
||||
cn += (14341LL * p4) >> 21;
|
||||
cn -= (50259LL * cndat * p) >> 23;
|
||||
cn += (88977LL * cndat) >> 9;
|
||||
cn -= (89565LL * p) >> 11;
|
||||
cn += 58857 << 3;
|
||||
stats->stat[0].svalue = cn >> 3;
|
||||
stats->stat[0].scale = FE_SCALE_DECIBEL;
|
||||
}
|
||||
|
||||
/* per-layer post viterbi BER (or PER? config dependent?) */
|
||||
stats = &c->post_bit_error;
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->len = layers;
|
||||
ret = reg_read(state, 0xeb, val, 10);
|
||||
if (ret < 0)
|
||||
for (i = 0; i < layers; i++)
|
||||
stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
else {
|
||||
for (i = 0; i < layers; i++) {
|
||||
stats->stat[i].scale = FE_SCALE_COUNTER;
|
||||
stats->stat[i].uvalue = val[i * 5] << 16
|
||||
| val[i * 5 + 1] << 8 | val[i * 5 + 2];
|
||||
}
|
||||
}
|
||||
stats = &c->post_bit_count;
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->len = layers;
|
||||
if (ret < 0)
|
||||
for (i = 0; i < layers; i++)
|
||||
stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
else {
|
||||
for (i = 0; i < layers; i++) {
|
||||
stats->stat[i].scale = FE_SCALE_COUNTER;
|
||||
stats->stat[i].uvalue =
|
||||
val[i * 5 + 3] << 8 | val[i * 5 + 4];
|
||||
stats->stat[i].uvalue *= 204 * 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const fe_transmit_mode_t tm_conv[] = {
|
||||
TRANSMISSION_MODE_2K,
|
||||
TRANSMISSION_MODE_4K,
|
||||
TRANSMISSION_MODE_8K,
|
||||
0
|
||||
};
|
||||
|
||||
static const fe_code_rate_t fec_conv_ter[] = {
|
||||
FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, 0, 0, 0
|
||||
};
|
||||
|
||||
static const fe_modulation_t mod_conv[] = {
|
||||
DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static int tc90522t_get_frontend(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
struct dtv_frontend_properties *c;
|
||||
struct dtv_fe_stats *stats;
|
||||
int ret, i;
|
||||
int layers;
|
||||
u8 val[15], mode;
|
||||
u32 cndat;
|
||||
|
||||
state = fe->demodulator_priv;
|
||||
c = &fe->dtv_property_cache;
|
||||
c->delivery_system = SYS_ISDBT;
|
||||
c->bandwidth_hz = 6000000;
|
||||
mode = 1;
|
||||
ret = reg_read(state, 0xb0, val, 1);
|
||||
if (ret == 0) {
|
||||
mode = (val[0] & 0xc0) >> 2;
|
||||
c->transmission_mode = tm_conv[mode];
|
||||
c->guard_interval = (val[0] & 0x30) >> 4;
|
||||
}
|
||||
|
||||
ret = reg_read(state, 0xb2, val, 6);
|
||||
layers = 0;
|
||||
if (ret == 0) {
|
||||
u8 v;
|
||||
|
||||
c->isdbt_partial_reception = val[0] & 0x01;
|
||||
c->isdbt_sb_mode = (val[0] & 0xc0) == 0x01;
|
||||
|
||||
/* layer A */
|
||||
v = (val[2] & 0x78) >> 3;
|
||||
if (v == 0x0f)
|
||||
c->layer[0].segment_count = 0;
|
||||
else {
|
||||
layers++;
|
||||
c->layer[0].segment_count = v;
|
||||
c->layer[0].fec = fec_conv_ter[(val[1] & 0x1c) >> 2];
|
||||
c->layer[0].modulation = mod_conv[(val[1] & 0xe0) >> 5];
|
||||
v = (val[1] & 0x03) << 1 | (val[2] & 0x80) >> 7;
|
||||
c->layer[0].interleaving = v;
|
||||
}
|
||||
|
||||
/* layer B */
|
||||
v = (val[3] & 0x03) << 1 | (val[4] & 0xc0) >> 6;
|
||||
if (v == 0x0f)
|
||||
c->layer[1].segment_count = 0;
|
||||
else {
|
||||
layers++;
|
||||
c->layer[1].segment_count = v;
|
||||
c->layer[1].fec = fec_conv_ter[(val[3] & 0xe0) >> 5];
|
||||
c->layer[1].modulation = mod_conv[(val[2] & 0x07)];
|
||||
c->layer[1].interleaving = (val[3] & 0x1c) >> 2;
|
||||
}
|
||||
|
||||
/* layer C */
|
||||
v = (val[5] & 0x1e) >> 1;
|
||||
if (v == 0x0f)
|
||||
c->layer[2].segment_count = 0;
|
||||
else {
|
||||
layers++;
|
||||
c->layer[2].segment_count = v;
|
||||
c->layer[2].fec = fec_conv_ter[(val[4] & 0x07)];
|
||||
c->layer[2].modulation = mod_conv[(val[4] & 0x38) >> 3];
|
||||
c->layer[2].interleaving = (val[5] & 0xe0) >> 5;
|
||||
}
|
||||
}
|
||||
|
||||
/* statistics */
|
||||
|
||||
stats = &c->strength;
|
||||
stats->len = 0;
|
||||
/* let the connected tuner set RSSI property cache */
|
||||
if (fe->ops.tuner_ops.get_rf_strength) {
|
||||
u16 dummy;
|
||||
|
||||
fe->ops.tuner_ops.get_rf_strength(fe, &dummy);
|
||||
}
|
||||
|
||||
stats = &c->cnr;
|
||||
stats->len = 1;
|
||||
stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
cndat = 0;
|
||||
ret = reg_read(state, 0x8b, val, 3);
|
||||
if (ret == 0)
|
||||
cndat = val[0] << 16 | val[1] << 8 | val[2];
|
||||
if (cndat != 0) {
|
||||
u32 p, tmp;
|
||||
s64 cn;
|
||||
|
||||
/*
|
||||
* cnr[mdB] = 0.024 P^4 - 1.6 P^3 + 39.8 P^2 + 549.1 P + 3096.5
|
||||
* (P = 10log10(5505024/cndat))
|
||||
*/
|
||||
/* cn = cnr << 3 (61.3 fixed point float */
|
||||
/* p = 10log10(5505024/cndat) << 24 (8.24 fixed point float)*/
|
||||
p = intlog10(5505024) - intlog10(cndat);
|
||||
p *= 10;
|
||||
|
||||
cn = 24772;
|
||||
cn += div64_s64(43827LL * p, 10) >> 24;
|
||||
tmp = p >> 8;
|
||||
cn += div64_s64(3184LL * tmp * tmp, 10) >> 32;
|
||||
tmp = p >> 13;
|
||||
cn -= div64_s64(128LL * tmp * tmp * tmp, 10) >> 33;
|
||||
tmp = p >> 18;
|
||||
cn += div64_s64(192LL * tmp * tmp * tmp * tmp, 1000) >> 24;
|
||||
|
||||
stats->stat[0].svalue = cn >> 3;
|
||||
stats->stat[0].scale = FE_SCALE_DECIBEL;
|
||||
}
|
||||
|
||||
/* per-layer post viterbi BER (or PER? config dependent?) */
|
||||
stats = &c->post_bit_error;
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->len = layers;
|
||||
ret = reg_read(state, 0x9d, val, 15);
|
||||
if (ret < 0)
|
||||
for (i = 0; i < layers; i++)
|
||||
stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
else {
|
||||
for (i = 0; i < layers; i++) {
|
||||
stats->stat[i].scale = FE_SCALE_COUNTER;
|
||||
stats->stat[i].uvalue = val[i * 3] << 16
|
||||
| val[i * 3 + 1] << 8 | val[i * 3 + 2];
|
||||
}
|
||||
}
|
||||
stats = &c->post_bit_count;
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->len = layers;
|
||||
if (ret < 0)
|
||||
for (i = 0; i < layers; i++)
|
||||
stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
else {
|
||||
for (i = 0; i < layers; i++) {
|
||||
stats->stat[i].scale = FE_SCALE_COUNTER;
|
||||
stats->stat[i].uvalue =
|
||||
val[9 + i * 2] << 8 | val[9 + i * 2 + 1];
|
||||
stats->stat[i].uvalue *= 204 * 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct reg_val reset_sat = { 0x03, 0x01 };
|
||||
static const struct reg_val reset_ter = { 0x01, 0x40 };
|
||||
|
||||
static int tc90522_set_frontend(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
int ret;
|
||||
|
||||
state = fe->demodulator_priv;
|
||||
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
ret = fe->ops.tuner_ops.set_params(fe);
|
||||
else
|
||||
ret = -ENODEV;
|
||||
if (ret < 0)
|
||||
goto failed;
|
||||
|
||||
if (fe->ops.delsys[0] == SYS_ISDBS) {
|
||||
ret = tc90522s_set_tsid(fe);
|
||||
if (ret < 0)
|
||||
goto failed;
|
||||
ret = reg_write(state, &reset_sat, 1);
|
||||
} else {
|
||||
ret = tc90522t_set_layers(fe);
|
||||
if (ret < 0)
|
||||
goto failed;
|
||||
ret = reg_write(state, &reset_ter, 1);
|
||||
}
|
||||
if (ret < 0)
|
||||
goto failed;
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
dev_warn(&state->tuner_i2c.dev, "(%s) failed. [adap%d-fe%d]\n",
|
||||
__func__, fe->dvb->num, fe->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc90522_get_tune_settings(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *settings)
|
||||
{
|
||||
if (fe->ops.delsys[0] == SYS_ISDBS) {
|
||||
settings->min_delay_ms = 250;
|
||||
settings->step_size = 1000;
|
||||
settings->max_drift = settings->step_size * 2;
|
||||
} else {
|
||||
settings->min_delay_ms = 400;
|
||||
settings->step_size = 142857;
|
||||
settings->max_drift = settings->step_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc90522_set_if_agc(struct dvb_frontend *fe, bool on)
|
||||
{
|
||||
struct reg_val agc_sat[] = {
|
||||
{ 0x0a, 0x00 },
|
||||
{ 0x10, 0x30 },
|
||||
{ 0x11, 0x00 },
|
||||
{ 0x03, 0x01 },
|
||||
};
|
||||
struct reg_val agc_ter[] = {
|
||||
{ 0x25, 0x00 },
|
||||
{ 0x23, 0x4c },
|
||||
{ 0x01, 0x40 },
|
||||
};
|
||||
struct tc90522_state *state;
|
||||
struct reg_val *rv;
|
||||
int num;
|
||||
|
||||
state = fe->demodulator_priv;
|
||||
if (fe->ops.delsys[0] == SYS_ISDBS) {
|
||||
agc_sat[0].val = on ? 0xff : 0x00;
|
||||
agc_sat[1].val |= 0x80;
|
||||
agc_sat[1].val |= on ? 0x01 : 0x00;
|
||||
agc_sat[2].val |= on ? 0x40 : 0x00;
|
||||
rv = agc_sat;
|
||||
num = ARRAY_SIZE(agc_sat);
|
||||
} else {
|
||||
agc_ter[0].val = on ? 0x40 : 0x00;
|
||||
agc_ter[1].val |= on ? 0x00 : 0x01;
|
||||
rv = agc_ter;
|
||||
num = ARRAY_SIZE(agc_ter);
|
||||
}
|
||||
return reg_write(state, rv, num);
|
||||
}
|
||||
|
||||
static const struct reg_val sleep_sat = { 0x17, 0x01 };
|
||||
static const struct reg_val sleep_ter = { 0x03, 0x90 };
|
||||
|
||||
static int tc90522_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
int ret;
|
||||
|
||||
state = fe->demodulator_priv;
|
||||
if (fe->ops.delsys[0] == SYS_ISDBS)
|
||||
ret = reg_write(state, &sleep_sat, 1);
|
||||
else {
|
||||
ret = reg_write(state, &sleep_ter, 1);
|
||||
if (ret == 0 && fe->ops.set_lna &&
|
||||
fe->dtv_property_cache.lna == LNA_AUTO) {
|
||||
fe->dtv_property_cache.lna = 0;
|
||||
ret = fe->ops.set_lna(fe);
|
||||
fe->dtv_property_cache.lna = LNA_AUTO;
|
||||
}
|
||||
}
|
||||
if (ret < 0)
|
||||
dev_warn(&state->tuner_i2c.dev,
|
||||
"(%s) failed. [adap%d-fe%d]\n",
|
||||
__func__, fe->dvb->num, fe->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct reg_val wakeup_sat = { 0x17, 0x00 };
|
||||
static const struct reg_val wakeup_ter = { 0x03, 0x80 };
|
||||
|
||||
static int tc90522_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Because the init sequence is not public,
|
||||
* the parent device/driver should have init'ed the device before.
|
||||
* just wake up the device here.
|
||||
*/
|
||||
|
||||
state = fe->demodulator_priv;
|
||||
if (fe->ops.delsys[0] == SYS_ISDBS)
|
||||
ret = reg_write(state, &wakeup_sat, 1);
|
||||
else {
|
||||
ret = reg_write(state, &wakeup_ter, 1);
|
||||
if (ret == 0 && fe->ops.set_lna &&
|
||||
fe->dtv_property_cache.lna == LNA_AUTO) {
|
||||
fe->dtv_property_cache.lna = 1;
|
||||
ret = fe->ops.set_lna(fe);
|
||||
fe->dtv_property_cache.lna = LNA_AUTO;
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
dev_warn(&state->tuner_i2c.dev,
|
||||
"(%s) failed. [adap%d-fe%d]\n",
|
||||
__func__, fe->dvb->num, fe->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* prefer 'all-layers' to 'none' as a default */
|
||||
if (fe->dtv_property_cache.isdbt_layer_enabled == 0)
|
||||
fe->dtv_property_cache.isdbt_layer_enabled = 7;
|
||||
return tc90522_set_if_agc(fe, true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* tuner I2C adapter functions
|
||||
*/
|
||||
|
||||
static int
|
||||
tc90522_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
struct i2c_msg *new_msgs;
|
||||
int i, j;
|
||||
int ret, rd_num;
|
||||
u8 wbuf[256];
|
||||
u8 *p, *bufend;
|
||||
|
||||
if (num <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
rd_num = 0;
|
||||
for (i = 0; i < num; i++)
|
||||
if (msgs[i].flags & I2C_M_RD)
|
||||
rd_num++;
|
||||
new_msgs = kmalloc(sizeof(*new_msgs) * (num + rd_num), GFP_KERNEL);
|
||||
if (!new_msgs)
|
||||
return -ENOMEM;
|
||||
|
||||
state = i2c_get_adapdata(adap);
|
||||
p = wbuf;
|
||||
bufend = wbuf + sizeof(wbuf);
|
||||
for (i = 0, j = 0; i < num; i++, j++) {
|
||||
new_msgs[j].addr = state->i2c_client->addr;
|
||||
new_msgs[j].flags = msgs[i].flags;
|
||||
|
||||
if (msgs[i].flags & I2C_M_RD) {
|
||||
new_msgs[j].flags &= ~I2C_M_RD;
|
||||
if (p + 2 > bufend)
|
||||
break;
|
||||
p[0] = TC90522_I2C_THRU_REG;
|
||||
p[1] = msgs[i].addr << 1 | 0x01;
|
||||
new_msgs[j].buf = p;
|
||||
new_msgs[j].len = 2;
|
||||
p += 2;
|
||||
j++;
|
||||
new_msgs[j].addr = state->i2c_client->addr;
|
||||
new_msgs[j].flags = msgs[i].flags;
|
||||
new_msgs[j].buf = msgs[i].buf;
|
||||
new_msgs[j].len = msgs[i].len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p + msgs[i].len + 2 > bufend)
|
||||
break;
|
||||
p[0] = TC90522_I2C_THRU_REG;
|
||||
p[1] = msgs[i].addr << 1;
|
||||
memcpy(p + 2, msgs[i].buf, msgs[i].len);
|
||||
new_msgs[j].buf = p;
|
||||
new_msgs[j].len = msgs[i].len + 2;
|
||||
p += new_msgs[j].len;
|
||||
}
|
||||
|
||||
if (i < num)
|
||||
ret = -ENOMEM;
|
||||
else
|
||||
ret = i2c_transfer(state->i2c_client->adapter, new_msgs, j);
|
||||
if (ret >= 0 && ret < j)
|
||||
ret = -EIO;
|
||||
kfree(new_msgs);
|
||||
return (ret == j) ? num : ret;
|
||||
}
|
||||
|
||||
static u32 tc90522_functionality(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm tc90522_tuner_i2c_algo = {
|
||||
.master_xfer = &tc90522_master_xfer,
|
||||
.functionality = &tc90522_functionality,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* I2C driver functions
|
||||
*/
|
||||
|
||||
static const struct dvb_frontend_ops tc90522_ops_sat = {
|
||||
.delsys = { SYS_ISDBS },
|
||||
.info = {
|
||||
.name = "Toshiba TC90522 ISDB-S module",
|
||||
.frequency_min = 950000,
|
||||
.frequency_max = 2150000,
|
||||
.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
|
||||
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
|
||||
},
|
||||
|
||||
.init = tc90522_init,
|
||||
.sleep = tc90522_sleep,
|
||||
.set_frontend = tc90522_set_frontend,
|
||||
.get_tune_settings = tc90522_get_tune_settings,
|
||||
|
||||
.get_frontend = tc90522s_get_frontend,
|
||||
.read_status = tc90522s_read_status,
|
||||
};
|
||||
|
||||
static const struct dvb_frontend_ops tc90522_ops_ter = {
|
||||
.delsys = { SYS_ISDBT },
|
||||
.info = {
|
||||
.name = "Toshiba TC90522 ISDB-T module",
|
||||
.frequency_min = 470000000,
|
||||
.frequency_max = 770000000,
|
||||
.frequency_stepsize = 142857,
|
||||
.caps = FE_CAN_INVERSION_AUTO |
|
||||
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
|
||||
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
|
||||
FE_CAN_HIERARCHY_AUTO,
|
||||
},
|
||||
|
||||
.init = tc90522_init,
|
||||
.sleep = tc90522_sleep,
|
||||
.set_frontend = tc90522_set_frontend,
|
||||
.get_tune_settings = tc90522_get_tune_settings,
|
||||
|
||||
.get_frontend = tc90522t_get_frontend,
|
||||
.read_status = tc90522t_read_status,
|
||||
};
|
||||
|
||||
|
||||
static int tc90522_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
struct tc90522_config *cfg;
|
||||
const struct dvb_frontend_ops *ops;
|
||||
struct i2c_adapter *adap;
|
||||
int ret;
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
state->i2c_client = client;
|
||||
|
||||
cfg = client->dev.platform_data;
|
||||
memcpy(&state->cfg, cfg, sizeof(state->cfg));
|
||||
cfg->fe = state->cfg.fe = &state->fe;
|
||||
ops = id->driver_data == 0 ? &tc90522_ops_sat : &tc90522_ops_ter;
|
||||
memcpy(&state->fe.ops, ops, sizeof(*ops));
|
||||
state->fe.demodulator_priv = state;
|
||||
|
||||
adap = &state->tuner_i2c;
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->algo = &tc90522_tuner_i2c_algo;
|
||||
adap->dev.parent = &client->dev;
|
||||
strlcpy(adap->name, "tc90522_sub", sizeof(adap->name));
|
||||
i2c_set_adapdata(adap, state);
|
||||
ret = i2c_add_adapter(adap);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
cfg->tuner_i2c = state->cfg.tuner_i2c = adap;
|
||||
|
||||
i2c_set_clientdata(client, &state->cfg);
|
||||
dev_info(&client->dev, "Toshiba TC90522 attached.\n");
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc90522_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tc90522_state *state;
|
||||
|
||||
state = cfg_to_state(i2c_get_clientdata(client));
|
||||
i2c_del_adapter(&state->tuner_i2c);
|
||||
kfree(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct i2c_device_id tc90522_id[] = {
|
||||
{ TC90522_I2C_DEV_SAT, 0 },
|
||||
{ TC90522_I2C_DEV_TER, 1 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tc90522_id);
|
||||
|
||||
static struct i2c_driver tc90522_driver = {
|
||||
.driver = {
|
||||
.name = "tc90522",
|
||||
},
|
||||
.probe = tc90522_probe,
|
||||
.remove = tc90522_remove,
|
||||
.id_table = tc90522_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(tc90522_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Toshiba TC90522 frontend");
|
||||
MODULE_AUTHOR("Akihiro TSUKADA");
|
||||
MODULE_LICENSE("GPL");
|
42
drivers/media/dvb-frontends/tc90522.h
Normal file
42
drivers/media/dvb-frontends/tc90522.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Toshiba TC90522 Demodulator
|
||||
*
|
||||
* Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation version 2.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The demod has 4 input (2xISDB-T and 2xISDB-S),
|
||||
* and provides independent sub modules for each input.
|
||||
* As the sub modules work in parallel and have the separate i2c addr's,
|
||||
* this driver treats each sub module as one demod device.
|
||||
*/
|
||||
|
||||
#ifndef TC90522_H
|
||||
#define TC90522_H
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
/* I2C device types */
|
||||
#define TC90522_I2C_DEV_SAT "tc90522sat"
|
||||
#define TC90522_I2C_DEV_TER "tc90522ter"
|
||||
|
||||
struct tc90522_config {
|
||||
/* [OUT] frontend returned by driver */
|
||||
struct dvb_frontend *fe;
|
||||
|
||||
/* [OUT] tuner I2C adapter returned by driver */
|
||||
struct i2c_adapter *tuner_i2c;
|
||||
};
|
||||
|
||||
#endif /* TC90522_H */
|
@ -1037,7 +1037,7 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||
ret = -EFAULT;
|
||||
goto error;
|
||||
} else {
|
||||
priv->warm = 1;
|
||||
priv->warm = true;
|
||||
}
|
||||
|
||||
cmd.args[0] = CMD_GET_FW_VERSION;
|
||||
|
@ -111,7 +111,7 @@ static int zl10039_write(struct zl10039_state *state,
|
||||
|
||||
if (1 + count > sizeof(buf)) {
|
||||
printk(KERN_WARNING
|
||||
"%s: i2c wr reg=%04x: len=%zd is too big!\n",
|
||||
"%s: i2c wr reg=%04x: len=%zu is too big!\n",
|
||||
KBUILD_MODNAME, reg, count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1157,6 +1157,10 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
|
||||
if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
|
||||
dev_err(fdtv->device,
|
||||
"invalid pmt_cmd_id %d\n", pmt_cmd_id);
|
||||
if (program_info_length > sizeof(c->operand) - 4 - write_pos) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&c->operand[write_pos], &msg[read_pos],
|
||||
program_info_length);
|
||||
@ -1180,6 +1184,12 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
|
||||
dev_err(fdtv->device, "invalid pmt_cmd_id %d "
|
||||
"at stream level\n", pmt_cmd_id);
|
||||
|
||||
if (es_info_length > sizeof(c->operand) - 4 -
|
||||
write_pos) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&c->operand[write_pos], &msg[read_pos],
|
||||
es_info_length);
|
||||
read_pos += es_info_length;
|
||||
|
@ -13,7 +13,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef ADV7343_REG_H
|
||||
#ifndef ADV7343_REGS_H
|
||||
#define ADV7343_REGS_H
|
||||
|
||||
struct adv7343_std_info {
|
||||
|
@ -1593,7 +1593,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
|
||||
bt->height += hdmi_read16(sd, 0x0b, 0xfff);
|
||||
bt->il_vfrontporch = hdmi_read16(sd, 0x2c, 0x1fff) / 2;
|
||||
bt->il_vsync = hdmi_read16(sd, 0x30, 0x1fff) / 2;
|
||||
bt->vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2;
|
||||
bt->il_vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2;
|
||||
}
|
||||
adv7604_fill_optional_dv_timings_fields(sd, timings);
|
||||
} else {
|
||||
|
@ -1435,6 +1435,8 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s:\n", __func__);
|
||||
|
||||
memset(timings, 0, sizeof(struct v4l2_dv_timings));
|
||||
|
||||
/* SDP block */
|
||||
if (state->mode == ADV7842_MODE_SDP)
|
||||
return -ENODATA;
|
||||
@ -1483,7 +1485,7 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
|
||||
hdmi_read(sd, 0x2d)) / 2;
|
||||
bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 256 +
|
||||
hdmi_read(sd, 0x31)) / 2;
|
||||
bt->vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 +
|
||||
bt->il_vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 +
|
||||
hdmi_read(sd, 0x35)) / 2;
|
||||
}
|
||||
adv7842_fill_optional_dv_timings_fields(sd, timings);
|
||||
|
@ -224,7 +224,7 @@ static inline unsigned int lpf_count_to_us(unsigned int count)
|
||||
}
|
||||
|
||||
/*
|
||||
* FIFO register pulse width count compuations
|
||||
* FIFO register pulse width count computations
|
||||
*/
|
||||
static u32 clock_divider_to_resolution(u16 divider)
|
||||
{
|
||||
|
@ -100,14 +100,14 @@ static int lm3560_enable_ctrl(struct lm3560_flash *flash,
|
||||
int rval;
|
||||
|
||||
if (led_no == LM3560_LED0) {
|
||||
if (on == true)
|
||||
if (on)
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x08, 0x08);
|
||||
else
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x08, 0x00);
|
||||
} else {
|
||||
if (on == true)
|
||||
if (on)
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x10, 0x10);
|
||||
else
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-mediabus.h>
|
||||
#include <media/v4l2-image-sizes.h>
|
||||
#include <media/ov7670.h>
|
||||
|
||||
MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
|
||||
@ -29,19 +30,6 @@ static bool debug;
|
||||
module_param(debug, bool, 0644);
|
||||
MODULE_PARM_DESC(debug, "Debug level (0-1)");
|
||||
|
||||
/*
|
||||
* Basic window sizes. These probably belong somewhere more globally
|
||||
* useful.
|
||||
*/
|
||||
#define VGA_WIDTH 640
|
||||
#define VGA_HEIGHT 480
|
||||
#define QVGA_WIDTH 320
|
||||
#define QVGA_HEIGHT 240
|
||||
#define CIF_WIDTH 352
|
||||
#define CIF_HEIGHT 288
|
||||
#define QCIF_WIDTH 176
|
||||
#define QCIF_HEIGHT 144
|
||||
|
||||
/*
|
||||
* The 7670 sits on i2c with ID 0x42
|
||||
*/
|
||||
|
@ -816,7 +816,7 @@ static void s5k5baf_hw_find_min_fiv(struct s5k5baf *state)
|
||||
"error setting frame interval: %d\n", err);
|
||||
state->error = -EINVAL;
|
||||
}
|
||||
};
|
||||
}
|
||||
v4l2_err(&state->sd, "cannot find correct frame interval\n");
|
||||
state->error = -ERANGE;
|
||||
}
|
||||
|
@ -660,7 +660,7 @@ static const struct v4l2_subdev_ops saa6752hs_ops = {
|
||||
static int saa6752hs_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
struct saa6752hs_state *h;
|
||||
struct v4l2_subdev *sd;
|
||||
struct v4l2_ctrl_handler *hdl;
|
||||
u8 addr = 0x13;
|
||||
@ -668,6 +668,8 @@ static int saa6752hs_probe(struct i2c_client *client,
|
||||
|
||||
v4l_info(client, "chip found @ 0x%x (%s)\n",
|
||||
client->addr << 1, client->adapter->name);
|
||||
|
||||
h = devm_kzalloc(&client->dev, sizeof(*h), GFP_KERNEL);
|
||||
if (h == NULL)
|
||||
return -ENOMEM;
|
||||
sd = &h->sd;
|
||||
@ -752,7 +754,6 @@ static int saa6752hs_probe(struct i2c_client *client,
|
||||
int err = hdl->error;
|
||||
|
||||
v4l2_ctrl_handler_free(hdl);
|
||||
kfree(h);
|
||||
return err;
|
||||
}
|
||||
v4l2_ctrl_cluster(3, &h->video_bitrate_mode);
|
||||
@ -767,7 +768,6 @@ static int saa6752hs_remove(struct i2c_client *client)
|
||||
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
v4l2_ctrl_handler_free(&to_state(sd)->hdl);
|
||||
kfree(to_state(sd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,9 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smiapp.h>
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
@ -297,8 +298,9 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
|
||||
*sensor->pixel_rate_parray->p_cur.p_s64 = pll->vt_pix_clk_freq_hz;
|
||||
*sensor->pixel_rate_csi->p_cur.p_s64 = pll->pixel_rate_csi;
|
||||
__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_parray,
|
||||
pll->vt_pix_clk_freq_hz);
|
||||
__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_csi, pll->pixel_rate_csi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -319,13 +321,7 @@ static void __smiapp_update_exposure_limits(struct smiapp_sensor *sensor)
|
||||
+ sensor->vblank->val
|
||||
- sensor->limits[SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MAX_MARGIN];
|
||||
|
||||
ctrl->maximum = max;
|
||||
if (ctrl->default_value > max)
|
||||
ctrl->default_value = max;
|
||||
if (ctrl->val > max)
|
||||
ctrl->val = max;
|
||||
if (ctrl->cur.val > max)
|
||||
ctrl->cur.val = max;
|
||||
__v4l2_ctrl_modify_range(ctrl, ctrl->minimum, max, ctrl->step, max);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -404,6 +400,14 @@ static void smiapp_update_mbus_formats(struct smiapp_sensor *sensor)
|
||||
pixel_order_str[pixel_order]);
|
||||
}
|
||||
|
||||
static const char * const smiapp_test_patterns[] = {
|
||||
"Disabled",
|
||||
"Solid Colour",
|
||||
"Eight Vertical Colour Bars",
|
||||
"Colour Bars With Fade to Grey",
|
||||
"Pseudorandom Sequence (PN9)",
|
||||
};
|
||||
|
||||
static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct smiapp_sensor *sensor =
|
||||
@ -477,6 +481,39 @@ static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
|
||||
return smiapp_pll_update(sensor);
|
||||
|
||||
case V4L2_CID_TEST_PATTERN: {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++)
|
||||
v4l2_ctrl_activate(
|
||||
sensor->test_data[i],
|
||||
ctrl->val ==
|
||||
V4L2_SMIAPP_TEST_PATTERN_MODE_SOLID_COLOUR);
|
||||
|
||||
return smiapp_write(
|
||||
sensor, SMIAPP_REG_U16_TEST_PATTERN_MODE, ctrl->val);
|
||||
}
|
||||
|
||||
case V4L2_CID_TEST_PATTERN_RED:
|
||||
return smiapp_write(
|
||||
sensor, SMIAPP_REG_U16_TEST_DATA_RED, ctrl->val);
|
||||
|
||||
case V4L2_CID_TEST_PATTERN_GREENR:
|
||||
return smiapp_write(
|
||||
sensor, SMIAPP_REG_U16_TEST_DATA_GREENR, ctrl->val);
|
||||
|
||||
case V4L2_CID_TEST_PATTERN_BLUE:
|
||||
return smiapp_write(
|
||||
sensor, SMIAPP_REG_U16_TEST_DATA_BLUE, ctrl->val);
|
||||
|
||||
case V4L2_CID_TEST_PATTERN_GREENB:
|
||||
return smiapp_write(
|
||||
sensor, SMIAPP_REG_U16_TEST_DATA_GREENB, ctrl->val);
|
||||
|
||||
case V4L2_CID_PIXEL_RATE:
|
||||
/* For v4l2_ctrl_s_ctrl_int64() used internally. */
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -489,10 +526,10 @@ static const struct v4l2_ctrl_ops smiapp_ctrl_ops = {
|
||||
static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||
unsigned int max;
|
||||
unsigned int max, i;
|
||||
int rval;
|
||||
|
||||
rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 7);
|
||||
rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12);
|
||||
if (rval)
|
||||
return rval;
|
||||
sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
|
||||
@ -535,6 +572,20 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
||||
&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
|
||||
|
||||
v4l2_ctrl_new_std_menu_items(&sensor->pixel_array->ctrl_handler,
|
||||
&smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN,
|
||||
ARRAY_SIZE(smiapp_test_patterns) - 1,
|
||||
0, 0, smiapp_test_patterns);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) {
|
||||
int max_value = (1 << sensor->csi_format->width) - 1;
|
||||
sensor->test_data[i] =
|
||||
v4l2_ctrl_new_std(
|
||||
&sensor->pixel_array->ctrl_handler,
|
||||
&smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i,
|
||||
0, max_value, 1, max_value);
|
||||
}
|
||||
|
||||
if (sensor->pixel_array->ctrl_handler.error) {
|
||||
dev_err(&client->dev,
|
||||
"pixel array controls initialization failed (%d)\n",
|
||||
@ -782,36 +833,25 @@ static void smiapp_update_blanking(struct smiapp_sensor *sensor)
|
||||
{
|
||||
struct v4l2_ctrl *vblank = sensor->vblank;
|
||||
struct v4l2_ctrl *hblank = sensor->hblank;
|
||||
int min, max;
|
||||
|
||||
vblank->minimum =
|
||||
max_t(int,
|
||||
sensor->limits[SMIAPP_LIMIT_MIN_FRAME_BLANKING_LINES],
|
||||
sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN] -
|
||||
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height);
|
||||
vblank->maximum =
|
||||
sensor->limits[SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN] -
|
||||
min = max_t(int,
|
||||
sensor->limits[SMIAPP_LIMIT_MIN_FRAME_BLANKING_LINES],
|
||||
sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN] -
|
||||
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height);
|
||||
max = sensor->limits[SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN] -
|
||||
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height;
|
||||
|
||||
vblank->val = clamp_t(int, vblank->val,
|
||||
vblank->minimum, vblank->maximum);
|
||||
vblank->default_value = vblank->minimum;
|
||||
vblank->val = vblank->val;
|
||||
vblank->cur.val = vblank->val;
|
||||
__v4l2_ctrl_modify_range(vblank, min, max, vblank->step, min);
|
||||
|
||||
hblank->minimum =
|
||||
max_t(int,
|
||||
sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN] -
|
||||
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width,
|
||||
sensor->limits[SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN]);
|
||||
hblank->maximum =
|
||||
sensor->limits[SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN] -
|
||||
min = max_t(int,
|
||||
sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN] -
|
||||
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width,
|
||||
sensor->limits[SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN]);
|
||||
max = sensor->limits[SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN] -
|
||||
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width;
|
||||
|
||||
hblank->val = clamp_t(int, hblank->val,
|
||||
hblank->minimum, hblank->maximum);
|
||||
hblank->default_value = hblank->minimum;
|
||||
hblank->val = hblank->val;
|
||||
hblank->cur.val = hblank->val;
|
||||
__v4l2_ctrl_modify_range(hblank, min, max, hblank->step, min);
|
||||
|
||||
__smiapp_update_exposure_limits(sensor);
|
||||
}
|
||||
@ -1272,7 +1312,7 @@ static void smiapp_power_off(struct smiapp_sensor *sensor)
|
||||
clk_disable_unprepare(sensor->ext_clk);
|
||||
usleep_range(5000, 5000);
|
||||
regulator_disable(sensor->vana);
|
||||
sensor->streaming = 0;
|
||||
sensor->streaming = false;
|
||||
}
|
||||
|
||||
static int smiapp_set_power(struct v4l2_subdev *subdev, int on)
|
||||
@ -1462,13 +1502,13 @@ static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
sensor->streaming = 1;
|
||||
sensor->streaming = true;
|
||||
rval = smiapp_start_streaming(sensor);
|
||||
if (rval < 0)
|
||||
sensor->streaming = 0;
|
||||
sensor->streaming = false;
|
||||
} else {
|
||||
rval = smiapp_stop_streaming(sensor);
|
||||
sensor->streaming = 0;
|
||||
sensor->streaming = false;
|
||||
}
|
||||
|
||||
return rval;
|
||||
@ -1664,17 +1704,34 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
|
||||
if (fmt->pad == ssd->source_pad) {
|
||||
u32 code = fmt->format.code;
|
||||
int rval = __smiapp_get_format(subdev, fh, fmt);
|
||||
bool range_changed = false;
|
||||
unsigned int i;
|
||||
|
||||
if (!rval && subdev == &sensor->src->sd) {
|
||||
const struct smiapp_csi_data_format *csi_format =
|
||||
smiapp_validate_csi_data_format(sensor, code);
|
||||
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||
|
||||
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||
if (csi_format->width !=
|
||||
sensor->csi_format->width)
|
||||
range_changed = true;
|
||||
|
||||
sensor->csi_format = csi_format;
|
||||
}
|
||||
|
||||
fmt->format.code = csi_format->code;
|
||||
}
|
||||
|
||||
mutex_unlock(&sensor->mutex);
|
||||
return rval;
|
||||
if (rval || !range_changed)
|
||||
return rval;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++)
|
||||
v4l2_ctrl_modify_range(
|
||||
sensor->test_data[i],
|
||||
0, (1 << sensor->csi_format->width) - 1, 1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sink pad. Width and height are changeable here. */
|
||||
|
@ -54,6 +54,8 @@
|
||||
(1000 + (SMIAPP_RESET_DELAY_CLOCKS * 1000 \
|
||||
+ (clk) / 1000 - 1) / ((clk) / 1000))
|
||||
|
||||
#define SMIAPP_COLOUR_COMPONENTS 4
|
||||
|
||||
#include "smiapp-limits.h"
|
||||
|
||||
struct smiapp_quirk;
|
||||
@ -241,6 +243,8 @@ struct smiapp_sensor {
|
||||
/* src controls */
|
||||
struct v4l2_ctrl *link_freq;
|
||||
struct v4l2_ctrl *pixel_rate_csi;
|
||||
/* test pattern colour components */
|
||||
struct v4l2_ctrl *test_data[SMIAPP_COLOUR_COMPONENTS];
|
||||
};
|
||||
|
||||
#define to_smiapp_subdev(_sd) \
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <media/soc_camera.h>
|
||||
#include <media/v4l2-clk.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-image-sizes.h>
|
||||
|
||||
/* you can check PLL/clock info */
|
||||
/* #define EXT_CLOCK 24000000 */
|
||||
@ -42,9 +43,6 @@
|
||||
#define MAX_WIDTH 2048
|
||||
#define MAX_HEIGHT 1536
|
||||
|
||||
#define VGA_WIDTH 640
|
||||
#define VGA_HEIGHT 480
|
||||
|
||||
/*
|
||||
* macro of read/write
|
||||
*/
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <media/v4l2-clk.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-image-sizes.h>
|
||||
|
||||
/*
|
||||
* register offset
|
||||
@ -360,10 +361,6 @@
|
||||
#define SCAL0_ACTRL 0x08 /* Auto scaling factor control */
|
||||
#define SCAL1_2_ACTRL 0x04 /* Auto scaling factor control */
|
||||
|
||||
#define VGA_WIDTH 640
|
||||
#define VGA_HEIGHT 480
|
||||
#define QVGA_WIDTH 320
|
||||
#define QVGA_HEIGHT 240
|
||||
#define OV772X_MAX_WIDTH VGA_WIDTH
|
||||
#define OV772X_MAX_HEIGHT VGA_HEIGHT
|
||||
|
||||
|
@ -564,13 +564,13 @@ static int ov9740_set_res(struct i2c_client *client, u32 width, u32 height)
|
||||
u32 y_start;
|
||||
u32 x_end;
|
||||
u32 y_end;
|
||||
bool scaling = 0;
|
||||
bool scaling = false;
|
||||
u32 scale_input_x;
|
||||
u32 scale_input_y;
|
||||
int ret;
|
||||
|
||||
if ((width != OV9740_MAX_WIDTH) || (height != OV9740_MAX_HEIGHT))
|
||||
scaling = 1;
|
||||
scaling = true;
|
||||
|
||||
/*
|
||||
* Try to use as much of the sensor area as possible when supporting
|
||||
|
@ -293,7 +293,7 @@ static int tda7432_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
if (t->mute->val) {
|
||||
lf |= TDA7432_MUTE;
|
||||
lr |= TDA7432_MUTE;
|
||||
lf |= TDA7432_MUTE;
|
||||
rf |= TDA7432_MUTE;
|
||||
rr |= TDA7432_MUTE;
|
||||
}
|
||||
/* Mute & update balance*/
|
||||
|
@ -775,25 +775,20 @@ static int tvp7002_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
|
||||
static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct tvp7002 *device = to_tvp7002(sd);
|
||||
int error = 0;
|
||||
int error;
|
||||
|
||||
if (device->streaming == enable)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
/* Set output state on (low impedance means stream on) */
|
||||
error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
|
||||
device->streaming = enable;
|
||||
} else {
|
||||
/* Set output state off (high impedance means stream off) */
|
||||
error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x03);
|
||||
if (error)
|
||||
v4l2_dbg(1, debug, sd, "Unable to stop streaming\n");
|
||||
|
||||
device->streaming = enable;
|
||||
/* low impedance: on, high impedance: off */
|
||||
error = tvp7002_write(sd, TVP7002_MISC_CTL_2, enable ? 0x00 : 0x03);
|
||||
if (error) {
|
||||
v4l2_dbg(1, debug, sd, "Fail to set streaming\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
return error;
|
||||
device->streaming = enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -30,22 +30,10 @@
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-mediabus.h>
|
||||
#include <media/v4l2-image-sizes.h>
|
||||
|
||||
#include "vs6624_regs.h"
|
||||
|
||||
#define VGA_WIDTH 640
|
||||
#define VGA_HEIGHT 480
|
||||
#define QVGA_WIDTH 320
|
||||
#define QVGA_HEIGHT 240
|
||||
#define QQVGA_WIDTH 160
|
||||
#define QQVGA_HEIGHT 120
|
||||
#define CIF_WIDTH 352
|
||||
#define CIF_HEIGHT 288
|
||||
#define QCIF_WIDTH 176
|
||||
#define QCIF_HEIGHT 144
|
||||
#define QQCIF_WIDTH 88
|
||||
#define QQCIF_HEIGHT 72
|
||||
|
||||
#define MAX_FRAME_RATE 30
|
||||
|
||||
struct vs6624 {
|
||||
|
@ -103,10 +103,8 @@ static long media_device_enum_entities(struct media_device *mdev,
|
||||
return -EINVAL;
|
||||
|
||||
u_ent.id = ent->id;
|
||||
if (ent->name) {
|
||||
strncpy(u_ent.name, ent->name, sizeof(u_ent.name));
|
||||
u_ent.name[sizeof(u_ent.name) - 1] = '\0';
|
||||
}
|
||||
if (ent->name)
|
||||
strlcpy(u_ent.name, ent->name, sizeof(u_ent.name));
|
||||
u_ent.type = ent->type;
|
||||
u_ent.revision = ent->revision;
|
||||
u_ent.flags = ent->flags;
|
||||
|
@ -192,7 +192,6 @@ static int media_open(struct inode *inode, struct file *filp)
|
||||
static int media_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct media_devnode *mdev = media_devnode_data(filp);
|
||||
int ret = 0;
|
||||
|
||||
if (mdev->fops->release)
|
||||
mdev->fops->release(filp);
|
||||
@ -201,7 +200,7 @@ static int media_release(struct inode *inode, struct file *filp)
|
||||
return value is ignored. */
|
||||
put_device(&mdev->dev);
|
||||
filp->private_data = NULL;
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations media_devnode_fops = {
|
||||
|
@ -629,11 +629,15 @@ static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
|
||||
{
|
||||
int y;
|
||||
int dw = 2 * dev->width;
|
||||
char tmp[dw + 32]; /* using a temp buffer is faster than direct */
|
||||
char *tmp; /* using a temp buffer is faster than direct */
|
||||
int cnt = 0;
|
||||
int len = 0;
|
||||
unsigned char r8 = 0x5; /* value for reg8 */
|
||||
|
||||
tmp = kmalloc(dw + 32, GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return 0;
|
||||
|
||||
if (rgb555)
|
||||
r8 |= 0x20; /* else use untranslated rgb = 565 */
|
||||
mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
|
||||
@ -664,6 +668,7 @@ static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
|
||||
len += dt;
|
||||
}
|
||||
}
|
||||
kfree(tmp);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ source "drivers/media/pci/ivtv/Kconfig"
|
||||
source "drivers/media/pci/zoran/Kconfig"
|
||||
source "drivers/media/pci/saa7146/Kconfig"
|
||||
source "drivers/media/pci/solo6x10/Kconfig"
|
||||
source "drivers/media/pci/tw68/Kconfig"
|
||||
endif
|
||||
|
||||
if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
|
||||
@ -41,6 +42,7 @@ source "drivers/media/pci/b2c2/Kconfig"
|
||||
source "drivers/media/pci/pluto2/Kconfig"
|
||||
source "drivers/media/pci/dm1105/Kconfig"
|
||||
source "drivers/media/pci/pt1/Kconfig"
|
||||
source "drivers/media/pci/pt3/Kconfig"
|
||||
source "drivers/media/pci/mantis/Kconfig"
|
||||
source "drivers/media/pci/ngene/Kconfig"
|
||||
source "drivers/media/pci/ddbridge/Kconfig"
|
||||
|
@ -7,10 +7,10 @@ obj-y += ttpci/ \
|
||||
pluto2/ \
|
||||
dm1105/ \
|
||||
pt1/ \
|
||||
pt3/ \
|
||||
mantis/ \
|
||||
ngene/ \
|
||||
ddbridge/ \
|
||||
b2c2/ \
|
||||
saa7146/
|
||||
|
||||
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
|
||||
@ -22,6 +22,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/
|
||||
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
|
||||
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
|
||||
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
|
||||
obj-$(CONFIG_VIDEO_TW68) += tw68/
|
||||
obj-$(CONFIG_VIDEO_MEYE) += meye/
|
||||
obj-$(CONFIG_STA2X11_VIP) += sta2x11/
|
||||
obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/
|
||||
|
@ -1531,7 +1531,6 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
|
||||
{
|
||||
struct bttv_buffer *old;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
|
||||
dprintk("switch_overlay: enter [new=%p]\n", new);
|
||||
if (new)
|
||||
@ -1551,7 +1550,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
|
||||
if (NULL == new)
|
||||
free_btres_lock(btv,fh,RESOURCE_OVERLAY);
|
||||
dprintk("switch_overlay: done\n");
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@ -3856,7 +3855,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
|
||||
|
||||
btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
|
||||
BT848_INT_MASK);
|
||||
};
|
||||
}
|
||||
|
||||
bttv_print_irqbits(stat,astat);
|
||||
|
||||
|
@ -674,11 +674,9 @@ static int dst_ca_release(struct inode *inode, struct file *file)
|
||||
|
||||
static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
|
||||
{
|
||||
ssize_t bytes_read = 0;
|
||||
|
||||
dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
|
||||
|
||||
return bytes_read;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
|
||||
|
@ -80,7 +80,7 @@ void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data,
|
||||
int period_elapsed = 0;
|
||||
int length;
|
||||
|
||||
dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zd\n", cxsc,
|
||||
dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zu\n", cxsc,
|
||||
pcm_data, num_bytes);
|
||||
|
||||
substream = cxsc->capture_pcm_substream;
|
||||
|
@ -130,7 +130,7 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
|
||||
}
|
||||
}
|
||||
if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
|
||||
CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
|
||||
CX18_INFO("loaded %s firmware (%zu bytes)\n", fn, fw->size);
|
||||
size = fw->size;
|
||||
release_firmware(fw);
|
||||
cx18_setup_page(cx, SCB_OFFSET);
|
||||
@ -164,7 +164,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
|
||||
|
||||
apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
|
||||
while (offset + sizeof(seghdr) < fw->size) {
|
||||
const u32 *shptr = src + offset / 4;
|
||||
const __le32 *shptr = (__force __le32 *)src + offset / 4;
|
||||
|
||||
seghdr.sync1 = le32_to_cpu(shptr[0]);
|
||||
seghdr.sync2 = le32_to_cpu(shptr[1]);
|
||||
@ -202,7 +202,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
|
||||
offset += seghdr.size;
|
||||
}
|
||||
if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
|
||||
CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
|
||||
CX18_INFO("loaded %s firmware V%08x (%zu bytes)\n",
|
||||
fn, apu_version, fw->size);
|
||||
size = fw->size;
|
||||
release_firmware(fw);
|
||||
|
@ -364,7 +364,7 @@ int cx18_stream_alloc(struct cx18_stream *s)
|
||||
((char __iomem *)cx->scb->cpu_mdl));
|
||||
|
||||
CX18_ERR("Too many buffers, cannot fit in SCB area\n");
|
||||
CX18_ERR("Max buffers = %zd\n",
|
||||
CX18_ERR("Max buffers = %zu\n",
|
||||
bufsz / sizeof(struct cx18_mdl_ent));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -3,12 +3,11 @@ config VIDEO_CX23885
|
||||
depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
|
||||
select SND_PCM
|
||||
select I2C_ALGOBIT
|
||||
select VIDEO_BTCX
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_TVEEPROM
|
||||
depends on RC_CORE
|
||||
select VIDEOBUF_DVB
|
||||
select VIDEOBUF_DMA_SG
|
||||
select VIDEOBUF2_DVB
|
||||
select VIDEOBUF2_DMA_SG
|
||||
select VIDEO_CX25840
|
||||
select VIDEO_CX2341X
|
||||
select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT
|
||||
@ -32,12 +31,16 @@ config VIDEO_CX23885
|
||||
select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
|
||||
---help---
|
||||
This is a video4linux driver for Conexant 23885 based
|
||||
|
@ -8,7 +8,6 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
|
||||
obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
|
||||
|
||||
ccflags-y += -Idrivers/media/i2c
|
||||
ccflags-y += -Idrivers/media/common
|
||||
ccflags-y += -Idrivers/media/tuners
|
||||
ccflags-y += -Idrivers/media/dvb-core
|
||||
ccflags-y += -Idrivers/media/dvb-frontends
|
||||
|
@ -16,10 +16,6 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -52,8 +48,8 @@
|
||||
* | DATA7| DATA6| DATA5| DATA4| DATA3| DATA2| DATA1| DATA0|
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
#include <media/videobuf-dvb.h>
|
||||
#include <dvb_demux.h>
|
||||
#include <dvb_frontend.h>
|
||||
#include "altera-ci.h"
|
||||
#include "dvb_ca_en50221.h"
|
||||
|
||||
|
@ -16,10 +16,6 @@
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __ALTERA_CI_H
|
||||
#define __ALTERA_CI_H
|
||||
|
@ -17,10 +17,6 @@
|
||||
* 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 "cx23885.h"
|
||||
|
@ -17,10 +17,6 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CIMAX2_H
|
||||
|
@ -18,10 +18,6 @@
|
||||
* 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 <linux/module.h>
|
||||
@ -865,6 +861,11 @@ static int cx23885_api_cmd(struct cx23885_dev *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cx23885_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
|
||||
{
|
||||
return cx23885_mbox_func(priv, cmd, in, out, data);
|
||||
}
|
||||
|
||||
static int cx23885_find_mailbox(struct cx23885_dev *dev)
|
||||
{
|
||||
u32 signature[4] = {
|
||||
@ -941,7 +942,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev)
|
||||
|
||||
if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
|
||||
printk(KERN_ERR "ERROR: Firmware size mismatch "
|
||||
"(have %zd, expected %d)\n",
|
||||
"(have %zu, expected %d)\n",
|
||||
firmware->size, CX23885_FIRM_IMAGE_SIZE);
|
||||
release_firmware(firmware);
|
||||
return -1;
|
||||
@ -1033,12 +1034,12 @@ static void cx23885_codec_settings(struct cx23885_dev *dev)
|
||||
cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
|
||||
dev->ts1.height, dev->ts1.width);
|
||||
|
||||
dev->mpeg_params.width = dev->ts1.width;
|
||||
dev->mpeg_params.height = dev->ts1.height;
|
||||
dev->mpeg_params.is_50hz =
|
||||
dev->cxhdl.width = dev->ts1.width;
|
||||
dev->cxhdl.height = dev->ts1.height;
|
||||
dev->cxhdl.is_50hz =
|
||||
(dev->encodernorm.id & V4L2_STD_625_50) != 0;
|
||||
|
||||
cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params);
|
||||
cx2341x_handler_setup(&dev->cxhdl);
|
||||
|
||||
cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
|
||||
cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
|
||||
@ -1137,85 +1138,107 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int bb_buf_setup(struct videobuf_queue *q,
|
||||
unsigned int *count, unsigned int *size)
|
||||
static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
|
||||
unsigned int *num_buffers, unsigned int *num_planes,
|
||||
unsigned int sizes[], void *alloc_ctxs[])
|
||||
{
|
||||
struct cx23885_fh *fh = q->priv_data;
|
||||
|
||||
fh->dev->ts1.ts_packet_size = mpeglinesize;
|
||||
fh->dev->ts1.ts_packet_count = mpeglines;
|
||||
|
||||
*size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
|
||||
*count = mpegbufs;
|
||||
struct cx23885_dev *dev = q->drv_priv;
|
||||
|
||||
dev->ts1.ts_packet_size = mpeglinesize;
|
||||
dev->ts1.ts_packet_count = mpeglines;
|
||||
*num_planes = 1;
|
||||
sizes[0] = mpeglinesize * mpeglines;
|
||||
*num_buffers = mpegbufs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bb_buf_prepare(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb, enum v4l2_field field)
|
||||
static int buffer_prepare(struct vb2_buffer *vb)
|
||||
{
|
||||
struct cx23885_fh *fh = q->priv_data;
|
||||
return cx23885_buf_prepare(q, &fh->dev->ts1,
|
||||
(struct cx23885_buffer *)vb,
|
||||
field);
|
||||
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
|
||||
struct cx23885_buffer *buf =
|
||||
container_of(vb, struct cx23885_buffer, vb);
|
||||
|
||||
return cx23885_buf_prepare(buf, &dev->ts1);
|
||||
}
|
||||
|
||||
static void bb_buf_queue(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb)
|
||||
static void buffer_finish(struct vb2_buffer *vb)
|
||||
{
|
||||
struct cx23885_fh *fh = q->priv_data;
|
||||
cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);
|
||||
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
|
||||
struct cx23885_buffer *buf = container_of(vb,
|
||||
struct cx23885_buffer, vb);
|
||||
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
|
||||
|
||||
cx23885_free_buffer(dev, buf);
|
||||
|
||||
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
static void bb_buf_release(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb)
|
||||
static void buffer_queue(struct vb2_buffer *vb)
|
||||
{
|
||||
cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
|
||||
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
|
||||
struct cx23885_buffer *buf = container_of(vb,
|
||||
struct cx23885_buffer, vb);
|
||||
|
||||
cx23885_buf_queue(&dev->ts1, buf);
|
||||
}
|
||||
|
||||
static struct videobuf_queue_ops cx23885_qops = {
|
||||
.buf_setup = bb_buf_setup,
|
||||
.buf_prepare = bb_buf_prepare,
|
||||
.buf_queue = bb_buf_queue,
|
||||
.buf_release = bb_buf_release,
|
||||
static int cx23885_start_streaming(struct vb2_queue *q, unsigned int count)
|
||||
{
|
||||
struct cx23885_dev *dev = q->drv_priv;
|
||||
struct cx23885_dmaqueue *dmaq = &dev->ts1.mpegq;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = cx23885_initialize_codec(dev, 1);
|
||||
if (ret == 0) {
|
||||
struct cx23885_buffer *buf = list_entry(dmaq->active.next,
|
||||
struct cx23885_buffer, queue);
|
||||
|
||||
cx23885_start_dma(&dev->ts1, dmaq, buf);
|
||||
return 0;
|
||||
}
|
||||
spin_lock_irqsave(&dev->slock, flags);
|
||||
while (!list_empty(&dmaq->active)) {
|
||||
struct cx23885_buffer *buf = list_entry(dmaq->active.next,
|
||||
struct cx23885_buffer, queue);
|
||||
|
||||
list_del(&buf->queue);
|
||||
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->slock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cx23885_stop_streaming(struct vb2_queue *q)
|
||||
{
|
||||
struct cx23885_dev *dev = q->drv_priv;
|
||||
|
||||
/* stop mpeg capture */
|
||||
cx23885_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
|
||||
CX23885_END_NOW, CX23885_MPEG_CAPTURE,
|
||||
CX23885_RAW_BITS_NONE);
|
||||
|
||||
msleep(500);
|
||||
cx23885_417_check_encoder(dev);
|
||||
cx23885_cancel_buffers(&dev->ts1);
|
||||
}
|
||||
|
||||
static struct vb2_ops cx23885_qops = {
|
||||
.queue_setup = queue_setup,
|
||||
.buf_prepare = buffer_prepare,
|
||||
.buf_finish = buffer_finish,
|
||||
.buf_queue = buffer_queue,
|
||||
.wait_prepare = vb2_ops_wait_prepare,
|
||||
.wait_finish = vb2_ops_wait_finish,
|
||||
.start_streaming = cx23885_start_streaming,
|
||||
.stop_streaming = cx23885_stop_streaming,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static const u32 *ctrl_classes[] = {
|
||||
cx2341x_mpeg_ctrls,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int cx23885_queryctrl(struct cx23885_dev *dev,
|
||||
struct v4l2_queryctrl *qctrl)
|
||||
{
|
||||
qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
|
||||
if (qctrl->id == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* MPEG V4L2 controls */
|
||||
if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
|
||||
qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx23885_querymenu(struct cx23885_dev *dev,
|
||||
struct v4l2_querymenu *qmenu)
|
||||
{
|
||||
struct v4l2_queryctrl qctrl;
|
||||
|
||||
qctrl.id = qmenu->id;
|
||||
cx23885_queryctrl(dev, &qctrl);
|
||||
return v4l2_ctrl_query_menu(qmenu, &qctrl,
|
||||
cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
|
||||
}
|
||||
|
||||
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
|
||||
*id = dev->tvnorm;
|
||||
return 0;
|
||||
@ -1223,29 +1246,26 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
|
||||
|
||||
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
|
||||
if (id & cx23885_tvnorms[i].id)
|
||||
break;
|
||||
if (i == ARRAY_SIZE(cx23885_tvnorms))
|
||||
return -EINVAL;
|
||||
dev->encodernorm = cx23885_tvnorms[i];
|
||||
|
||||
/* Have the drier core notify the subdevices */
|
||||
mutex_lock(&dev->lock);
|
||||
cx23885_set_tvnorm(dev, id);
|
||||
mutex_unlock(&dev->lock);
|
||||
|
||||
return 0;
|
||||
ret = cx23885_set_tvnorm(dev, id);
|
||||
if (!ret)
|
||||
dev->encodernorm = cx23885_tvnorms[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vidioc_enum_input(struct file *file, void *priv,
|
||||
struct v4l2_input *i)
|
||||
{
|
||||
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
dprintk(1, "%s()\n", __func__);
|
||||
return cx23885_enum_input(dev, i);
|
||||
}
|
||||
@ -1263,8 +1283,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
|
||||
static int vidioc_g_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *t)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
@ -1281,8 +1300,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
|
||||
static int vidioc_s_tuner(struct file *file, void *priv,
|
||||
const struct v4l2_tuner *t)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
@ -1296,8 +1314,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
|
||||
static int vidioc_g_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
@ -1315,27 +1332,10 @@ static int vidioc_s_frequency(struct file *file, void *priv,
|
||||
return cx23885_set_frequency(file, priv, f);
|
||||
}
|
||||
|
||||
static int vidioc_g_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctl)
|
||||
{
|
||||
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
|
||||
|
||||
return cx23885_get_control(dev, ctl);
|
||||
}
|
||||
|
||||
static int vidioc_s_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctl)
|
||||
{
|
||||
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
|
||||
|
||||
return cx23885_set_control(dev, ctl);
|
||||
}
|
||||
|
||||
static int vidioc_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *cap)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
struct cx23885_tsport *tsport = &dev->ts1;
|
||||
|
||||
strlcpy(cap->driver, dev->name, sizeof(cap->driver));
|
||||
@ -1368,8 +1368,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
|
||||
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
|
||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
@ -1378,285 +1377,63 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
|
||||
f->fmt.pix.colorspace = 0;
|
||||
f->fmt.pix.width = dev->ts1.width;
|
||||
f->fmt.pix.height = dev->ts1.height;
|
||||
f->fmt.pix.field = fh->mpegq.field;
|
||||
dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
|
||||
dev->ts1.width, dev->ts1.height, fh->mpegq.field);
|
||||
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
|
||||
dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
|
||||
dev->ts1.width, dev->ts1.height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
|
||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage =
|
||||
dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
|
||||
f->fmt.pix.colorspace = 0;
|
||||
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
|
||||
dev->ts1.width, dev->ts1.height, fh->mpegq.field);
|
||||
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
|
||||
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
|
||||
dev->ts1.width, dev->ts1.height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
|
||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage =
|
||||
dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
|
||||
f->fmt.pix.colorspace = 0;
|
||||
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
|
||||
dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
|
||||
f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_reqbufs(struct file *file, void *priv,
|
||||
struct v4l2_requestbuffers *p)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
|
||||
return videobuf_reqbufs(&fh->mpegq, p);
|
||||
}
|
||||
|
||||
static int vidioc_querybuf(struct file *file, void *priv,
|
||||
struct v4l2_buffer *p)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
|
||||
return videobuf_querybuf(&fh->mpegq, p);
|
||||
}
|
||||
|
||||
static int vidioc_qbuf(struct file *file, void *priv,
|
||||
struct v4l2_buffer *p)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
|
||||
return videobuf_qbuf(&fh->mpegq, p);
|
||||
}
|
||||
|
||||
static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
|
||||
{
|
||||
struct cx23885_fh *fh = priv;
|
||||
|
||||
return videobuf_dqbuf(&fh->mpegq, b, file->f_flags & O_NONBLOCK);
|
||||
}
|
||||
|
||||
|
||||
static int vidioc_streamon(struct file *file, void *priv,
|
||||
enum v4l2_buf_type i)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
|
||||
return videobuf_streamon(&fh->mpegq);
|
||||
}
|
||||
|
||||
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
|
||||
return videobuf_streamoff(&fh->mpegq);
|
||||
}
|
||||
|
||||
static int vidioc_g_ext_ctrls(struct file *file, void *priv,
|
||||
struct v4l2_ext_controls *f)
|
||||
{
|
||||
struct cx23885_fh *fh = priv;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
||||
return -EINVAL;
|
||||
return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
|
||||
}
|
||||
|
||||
static int vidioc_s_ext_ctrls(struct file *file, void *priv,
|
||||
struct v4l2_ext_controls *f)
|
||||
{
|
||||
struct cx23885_fh *fh = priv;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx2341x_mpeg_params p;
|
||||
int err;
|
||||
|
||||
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
||||
return -EINVAL;
|
||||
|
||||
p = dev->mpeg_params;
|
||||
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);
|
||||
|
||||
if (err == 0) {
|
||||
err = cx2341x_update(dev, cx23885_mbox_func,
|
||||
&dev->mpeg_params, &p);
|
||||
dev->mpeg_params = p;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vidioc_try_ext_ctrls(struct file *file, void *priv,
|
||||
struct v4l2_ext_controls *f)
|
||||
{
|
||||
struct cx23885_fh *fh = priv;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx2341x_mpeg_params p;
|
||||
int err;
|
||||
|
||||
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
||||
return -EINVAL;
|
||||
|
||||
p = dev->mpeg_params;
|
||||
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vidioc_log_status(struct file *file, void *priv)
|
||||
{
|
||||
struct cx23885_fh *fh = priv;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
char name[32 + 2];
|
||||
|
||||
snprintf(name, sizeof(name), "%s/2", dev->name);
|
||||
printk(KERN_INFO
|
||||
"%s/2: ============ START LOG STATUS ============\n",
|
||||
dev->name);
|
||||
call_all(dev, core, log_status);
|
||||
cx2341x_log_status(&dev->mpeg_params, name);
|
||||
printk(KERN_INFO
|
||||
"%s/2: ============= END LOG STATUS =============\n",
|
||||
dev->name);
|
||||
v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_querymenu(struct file *file, void *priv,
|
||||
struct v4l2_querymenu *a)
|
||||
{
|
||||
struct cx23885_fh *fh = priv;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
return cx23885_querymenu(dev, a);
|
||||
}
|
||||
|
||||
static int vidioc_queryctrl(struct file *file, void *priv,
|
||||
struct v4l2_queryctrl *c)
|
||||
{
|
||||
struct cx23885_fh *fh = priv;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
return cx23885_queryctrl(dev, c);
|
||||
}
|
||||
|
||||
static int mpeg_open(struct file *file)
|
||||
{
|
||||
struct cx23885_dev *dev = video_drvdata(file);
|
||||
struct cx23885_fh *fh;
|
||||
|
||||
dprintk(2, "%s()\n", __func__);
|
||||
|
||||
/* allocate + initialize per filehandle data */
|
||||
fh = kzalloc(sizeof(*fh), GFP_KERNEL);
|
||||
if (!fh)
|
||||
return -ENOMEM;
|
||||
|
||||
file->private_data = fh;
|
||||
fh->dev = dev;
|
||||
|
||||
videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops,
|
||||
&dev->pci->dev, &dev->ts1.slock,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_FIELD_INTERLACED,
|
||||
sizeof(struct cx23885_buffer),
|
||||
fh, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpeg_release(struct file *file)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
dprintk(2, "%s()\n", __func__);
|
||||
|
||||
/* FIXME: Review this crap */
|
||||
/* Shut device down on last close */
|
||||
if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
|
||||
if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
|
||||
/* stop mpeg capture */
|
||||
cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
|
||||
CX23885_END_NOW, CX23885_MPEG_CAPTURE,
|
||||
CX23885_RAW_BITS_NONE);
|
||||
|
||||
msleep(500);
|
||||
cx23885_417_check_encoder(dev);
|
||||
|
||||
cx23885_cancel_buffers(&fh->dev->ts1);
|
||||
}
|
||||
}
|
||||
|
||||
if (fh->mpegq.streaming)
|
||||
videobuf_streamoff(&fh->mpegq);
|
||||
if (fh->mpegq.reading)
|
||||
videobuf_read_stop(&fh->mpegq);
|
||||
|
||||
videobuf_mmap_free(&fh->mpegq);
|
||||
file->private_data = NULL;
|
||||
kfree(fh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t mpeg_read(struct file *file, char __user *data,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
dprintk(2, "%s()\n", __func__);
|
||||
|
||||
/* Deal w/ A/V decoder * and mpeg encoder sync issues. */
|
||||
/* Start mpeg encoder on first read. */
|
||||
if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
|
||||
if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
|
||||
if (cx23885_initialize_codec(dev, 1) < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
|
||||
file->f_flags & O_NONBLOCK);
|
||||
}
|
||||
|
||||
static unsigned int mpeg_poll(struct file *file,
|
||||
struct poll_table_struct *wait)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
dprintk(2, "%s\n", __func__);
|
||||
|
||||
return videobuf_poll_stream(file, &fh->mpegq, wait);
|
||||
}
|
||||
|
||||
static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
dprintk(2, "%s()\n", __func__);
|
||||
|
||||
return videobuf_mmap_mapper(&fh->mpegq, vma);
|
||||
}
|
||||
|
||||
static struct v4l2_file_operations mpeg_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mpeg_open,
|
||||
.release = mpeg_release,
|
||||
.read = mpeg_read,
|
||||
.poll = mpeg_poll,
|
||||
.mmap = mpeg_mmap,
|
||||
.ioctl = video_ioctl2,
|
||||
.open = v4l2_fh_open,
|
||||
.release = vb2_fop_release,
|
||||
.read = vb2_fop_read,
|
||||
.poll = vb2_fop_poll,
|
||||
.unlocked_ioctl = video_ioctl2,
|
||||
.mmap = vb2_fop_mmap,
|
||||
};
|
||||
|
||||
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
|
||||
@ -1669,25 +1446,19 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
|
||||
.vidioc_s_tuner = vidioc_s_tuner,
|
||||
.vidioc_g_frequency = vidioc_g_frequency,
|
||||
.vidioc_s_frequency = vidioc_s_frequency,
|
||||
.vidioc_s_ctrl = vidioc_s_ctrl,
|
||||
.vidioc_g_ctrl = vidioc_g_ctrl,
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
|
||||
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
|
||||
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
|
||||
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
|
||||
.vidioc_reqbufs = vidioc_reqbufs,
|
||||
.vidioc_querybuf = vidioc_querybuf,
|
||||
.vidioc_qbuf = vidioc_qbuf,
|
||||
.vidioc_dqbuf = vidioc_dqbuf,
|
||||
.vidioc_streamon = vidioc_streamon,
|
||||
.vidioc_streamoff = vidioc_streamoff,
|
||||
.vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
|
||||
.vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
|
||||
.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
|
||||
.vidioc_reqbufs = vb2_ioctl_reqbufs,
|
||||
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
|
||||
.vidioc_querybuf = vb2_ioctl_querybuf,
|
||||
.vidioc_qbuf = vb2_ioctl_qbuf,
|
||||
.vidioc_dqbuf = vb2_ioctl_dqbuf,
|
||||
.vidioc_streamon = vb2_ioctl_streamon,
|
||||
.vidioc_streamoff = vb2_ioctl_streamoff,
|
||||
.vidioc_log_status = vidioc_log_status,
|
||||
.vidioc_querymenu = vidioc_querymenu,
|
||||
.vidioc_queryctrl = vidioc_queryctrl,
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.vidioc_g_chip_info = cx23885_g_chip_info,
|
||||
.vidioc_g_register = cx23885_g_register,
|
||||
@ -1711,6 +1482,7 @@ void cx23885_417_unregister(struct cx23885_dev *dev)
|
||||
video_unregister_device(dev->v4l_device);
|
||||
else
|
||||
video_device_release(dev->v4l_device);
|
||||
v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
|
||||
dev->v4l_device = NULL;
|
||||
}
|
||||
}
|
||||
@ -1742,6 +1514,7 @@ int cx23885_417_register(struct cx23885_dev *dev)
|
||||
/* FIXME: Port1 hardcoded here */
|
||||
int err = -ENODEV;
|
||||
struct cx23885_tsport *tsport = &dev->ts1;
|
||||
struct vb2_queue *q;
|
||||
|
||||
dprintk(1, "%s()\n", __func__);
|
||||
|
||||
@ -1757,14 +1530,36 @@ int cx23885_417_register(struct cx23885_dev *dev)
|
||||
tsport->height = 576;
|
||||
|
||||
tsport->width = 720;
|
||||
cx2341x_fill_defaults(&dev->mpeg_params);
|
||||
|
||||
dev->mpeg_params.port = CX2341X_PORT_SERIAL;
|
||||
dev->cxhdl.port = CX2341X_PORT_SERIAL;
|
||||
err = cx2341x_handler_init(&dev->cxhdl, 50);
|
||||
if (err)
|
||||
return err;
|
||||
dev->cxhdl.priv = dev;
|
||||
dev->cxhdl.func = cx23885_api_func;
|
||||
cx2341x_handler_set_50hz(&dev->cxhdl, tsport->height == 576);
|
||||
v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL);
|
||||
|
||||
/* Allocate and initialize V4L video device */
|
||||
dev->v4l_device = cx23885_video_dev_alloc(tsport,
|
||||
dev->pci, &cx23885_mpeg_template, "mpeg");
|
||||
q = &dev->vb2_mpegq;
|
||||
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
|
||||
q->gfp_flags = GFP_DMA32;
|
||||
q->min_buffers_needed = 2;
|
||||
q->drv_priv = dev;
|
||||
q->buf_struct_size = sizeof(struct cx23885_buffer);
|
||||
q->ops = &cx23885_qops;
|
||||
q->mem_ops = &vb2_dma_sg_memops;
|
||||
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
|
||||
q->lock = &dev->lock;
|
||||
|
||||
err = vb2_queue_init(q);
|
||||
if (err < 0)
|
||||
return err;
|
||||
video_set_drvdata(dev->v4l_device, dev);
|
||||
dev->v4l_device->lock = &dev->lock;
|
||||
dev->v4l_device->queue = q;
|
||||
err = video_register_device(dev->v4l_device,
|
||||
VFL_TYPE_GRABBER, -1);
|
||||
if (err < 0) {
|
||||
|
@ -15,10 +15,6 @@
|
||||
* 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 <linux/module.h>
|
||||
@ -84,6 +80,82 @@ MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]");
|
||||
#define AUD_INT_MCHG_IRQ (1 << 21)
|
||||
#define GP_COUNT_CONTROL_RESET 0x3
|
||||
|
||||
static int cx23885_alsa_dma_init(struct cx23885_audio_dev *chip, int nr_pages)
|
||||
{
|
||||
struct cx23885_audio_buffer *buf = chip->buf;
|
||||
struct page *pg;
|
||||
int i;
|
||||
|
||||
buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
|
||||
if (NULL == buf->vaddr) {
|
||||
dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
|
||||
(unsigned long)buf->vaddr,
|
||||
nr_pages << PAGE_SHIFT);
|
||||
|
||||
memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
|
||||
buf->nr_pages = nr_pages;
|
||||
|
||||
buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
|
||||
if (NULL == buf->sglist)
|
||||
goto vzalloc_err;
|
||||
|
||||
sg_init_table(buf->sglist, buf->nr_pages);
|
||||
for (i = 0; i < buf->nr_pages; i++) {
|
||||
pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
|
||||
if (NULL == pg)
|
||||
goto vmalloc_to_page_err;
|
||||
sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
vmalloc_to_page_err:
|
||||
vfree(buf->sglist);
|
||||
buf->sglist = NULL;
|
||||
vzalloc_err:
|
||||
vfree(buf->vaddr);
|
||||
buf->vaddr = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int cx23885_alsa_dma_map(struct cx23885_audio_dev *dev)
|
||||
{
|
||||
struct cx23885_audio_buffer *buf = dev->buf;
|
||||
|
||||
buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist,
|
||||
buf->nr_pages, PCI_DMA_FROMDEVICE);
|
||||
|
||||
if (0 == buf->sglen) {
|
||||
pr_warn("%s: cx23885_alsa_map_sg failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx23885_alsa_dma_unmap(struct cx23885_audio_dev *dev)
|
||||
{
|
||||
struct cx23885_audio_buffer *buf = dev->buf;
|
||||
|
||||
if (!buf->sglen)
|
||||
return 0;
|
||||
|
||||
dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE);
|
||||
buf->sglen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx23885_alsa_dma_free(struct cx23885_audio_buffer *buf)
|
||||
{
|
||||
vfree(buf->sglist);
|
||||
buf->sglist = NULL;
|
||||
vfree(buf->vaddr);
|
||||
buf->vaddr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* BOARD Specific: Sets audio DMA
|
||||
*/
|
||||
@ -198,15 +270,18 @@ int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask)
|
||||
|
||||
static int dsp_buffer_free(struct cx23885_audio_dev *chip)
|
||||
{
|
||||
struct cx23885_riscmem *risc;
|
||||
|
||||
BUG_ON(!chip->dma_size);
|
||||
|
||||
dprintk(2, "Freeing buffer\n");
|
||||
videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
|
||||
videobuf_dma_free(chip->dma_risc);
|
||||
btcx_riscmem_free(chip->pci, &chip->buf->risc);
|
||||
cx23885_alsa_dma_unmap(chip);
|
||||
cx23885_alsa_dma_free(chip->buf);
|
||||
risc = &chip->buf->risc;
|
||||
pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma);
|
||||
kfree(chip->buf);
|
||||
|
||||
chip->dma_risc = NULL;
|
||||
chip->buf = NULL;
|
||||
chip->dma_size = 0;
|
||||
|
||||
return 0;
|
||||
@ -289,6 +364,7 @@ static int snd_cx23885_close(struct snd_pcm_substream *substream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hw_params callback
|
||||
*/
|
||||
@ -296,8 +372,6 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *hw_params)
|
||||
{
|
||||
struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
|
||||
struct videobuf_dmabuf *dma;
|
||||
|
||||
struct cx23885_audio_buffer *buf;
|
||||
int ret;
|
||||
|
||||
@ -318,19 +392,18 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
|
||||
return -ENOMEM;
|
||||
|
||||
buf->bpl = chip->period_size;
|
||||
chip->buf = buf;
|
||||
|
||||
dma = &buf->dma;
|
||||
videobuf_dma_init(dma);
|
||||
ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
|
||||
ret = cx23885_alsa_dma_init(chip,
|
||||
(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = videobuf_dma_map(&chip->pci->dev, dma);
|
||||
ret = cx23885_alsa_dma_map(chip);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
|
||||
ret = cx23885_risc_databuffer(chip->pci, &buf->risc, buf->sglist,
|
||||
chip->period_size, chip->num_periods, 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
@ -340,10 +413,7 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
|
||||
buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
|
||||
buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
|
||||
|
||||
chip->buf = buf;
|
||||
chip->dma_risc = dma;
|
||||
|
||||
substream->runtime->dma_area = chip->dma_risc->vaddr;
|
||||
substream->runtime->dma_area = chip->buf->vaddr;
|
||||
substream->runtime->dma_bytes = chip->dma_size;
|
||||
substream->runtime->dma_addr = 0;
|
||||
|
||||
@ -351,6 +421,7 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
error:
|
||||
kfree(buf);
|
||||
chip->buf = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,6 @@
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "cx23885.h"
|
||||
|
@ -14,11 +14,6 @@
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _CX23885_AV_H_
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user