mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - removal of sn9c102. This device driver was replaced a long time ago by gspca - solo6x10 and go7007 webcam drivers moved from staging into mainstream. They were waiting for an API to allow setting the image detection matrix - SDR drivers moved from staging into mainstream: sdr-msi3101 (renamed as msi2500) and rtl2832 - added SDR driver for airspy - added demux driver: si2165 - rework at several RC subsystem, making the code for RC-5 SZ variant to be added at the standard RC5 decoder - added decoder for the XMP IR protocol - tuner driver moved from staging into mainstream: msi3101 (renamed as msi001) - added documentation for some additional SDR pixfmt - some device tree bindings documented - added support for exynos3250 at s5p-jpeg - remove the obsolete, unmaintained and broken mx1_camera driver - added support for remote controllers at au0828 driver - added a RC driver: sunxi-cir - several driver fixes, enhancements and cleanups. * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (455 commits) [media] cx23885: fix UNSET/TUNER_ABSENT confusion [media] coda: fix build error by making reset control optional [media] radio-miropcm20: fix sparse NULL pointer warning [media] MAINTAINERS: Update go7007 pattern [media] MAINTAINERS: Update solo6x10 patterns [media] media: atmel-isi: add primary DT support [media] media: atmel-isi: convert the pdata from pointer to structure [media] media: atmel-isi: add v4l2 async probe support [media] rcar_vin: add devicetree support [media] media: pxa_camera device-tree support [media] media: mt9m111: add device-tree suppport [media] soc_camera: add support for dt binding soc_camera drivers [media] media: soc_camera: pxa_camera documentation device-tree support [media] media: mt9m111: add device-tree documentation [media] s5p-mfc: remove unnecessary calling to function video_devdata() [media] s5p-jpeg: add chroma subsampling adjustment for Exynos3250 [media] s5p-jpeg: Prevent erroneous downscaling for Exynos3250 SoC [media] s5p-jpeg: Assure proper crop rectangle initialization [media] s5p-jpeg: fix g_selection op [media] s5p-jpeg: Adjust jpeg_bound_align_image to Exynos3250 needs ...
This commit is contained in:
commit
f4d33337ea
442 changed files with 16105 additions and 17004 deletions
|
|
@ -59,6 +59,13 @@ config MEDIA_RADIO_SUPPORT
|
|||
support radio reception. Disabling this option will
|
||||
disable support for them.
|
||||
|
||||
config MEDIA_SDR_SUPPORT
|
||||
bool "Software defined radio support"
|
||||
---help---
|
||||
Enable software defined radio support.
|
||||
|
||||
Say Y when you have a software defined radio device.
|
||||
|
||||
config MEDIA_RC_SUPPORT
|
||||
bool "Remote Controller support"
|
||||
depends on INPUT
|
||||
|
|
@ -95,7 +102,7 @@ config MEDIA_CONTROLLER
|
|||
config VIDEO_DEV
|
||||
tristate
|
||||
depends on MEDIA_SUPPORT
|
||||
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
|
||||
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT
|
||||
default y
|
||||
|
||||
config VIDEO_V4L2_SUBDEV_API
|
||||
|
|
@ -171,10 +178,11 @@ comment "Media ancillary drivers (tuners, sensors, i2c, frontends)"
|
|||
|
||||
config MEDIA_SUBDRV_AUTOSELECT
|
||||
bool "Autoselect ancillary drivers (tuners, sensors, i2c, frontends)"
|
||||
depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT
|
||||
depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT || MEDIA_SDR_SUPPORT
|
||||
depends on HAS_IOMEM
|
||||
select I2C
|
||||
select I2C_MUX
|
||||
select SPI
|
||||
default y
|
||||
help
|
||||
By default, a media driver auto-selects all possible ancillary
|
||||
|
|
|
|||
|
|
@ -533,13 +533,12 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
|
|||
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
|
||||
saa7146_vbi_uops.init(dev,vv);
|
||||
|
||||
fmt = &vv->ov_fb.fmt;
|
||||
fmt->width = vv->standard->h_max_out;
|
||||
fmt->height = vv->standard->v_max_out;
|
||||
fmt->pixelformat = V4L2_PIX_FMT_RGB565;
|
||||
fmt->bytesperline = 2 * fmt->width;
|
||||
fmt->sizeimage = fmt->bytesperline * fmt->height;
|
||||
fmt->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
vv->ov_fb.fmt.width = vv->standard->h_max_out;
|
||||
vv->ov_fb.fmt.height = vv->standard->v_max_out;
|
||||
vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
|
||||
vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width;
|
||||
vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height;
|
||||
vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB;
|
||||
|
||||
fmt = &vv->video_fmt;
|
||||
fmt->width = 384;
|
||||
|
|
@ -613,7 +612,6 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
|
|||
vfd->lock = &dev->v4l2_lock;
|
||||
vfd->v4l2_dev = &dev->v4l2_dev;
|
||||
vfd->tvnorms = 0;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
|
||||
for (i = 0; i < dev->ext_vv_data->num_stds; i++)
|
||||
vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
|
||||
strlcpy(vfd->name, name, sizeof(vfd->name));
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ config SMS_SIANO_DEBUGFS
|
|||
bool "Enable debugfs for smsdvb"
|
||||
depends on SMS_SIANO_MDTV
|
||||
depends on DEBUG_FS
|
||||
depends on SMS_USB_DRV
|
||||
depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV
|
||||
depends on SMS_USB_DRV = SMS_SDIO_DRV
|
||||
|
||||
---help---
|
||||
Choose Y to enable visualizing a dump of the frontend
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
|
|||
|
||||
dev->priv = coredev;
|
||||
dev->driver_type = RC_DRIVER_IR_RAW;
|
||||
rc_set_allowed_protocols(dev, RC_BIT_ALL);
|
||||
dev->allowed_protocols = RC_BIT_ALL;
|
||||
dev->map_name = sms_get_board(board_id)->rc_codes;
|
||||
dev->driver_name = MODULE_NAME;
|
||||
|
||||
|
|
|
|||
|
|
@ -244,6 +244,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_TVSTICK_CT2_4400 0x3014
|
||||
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
|
||||
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
|
||||
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
|
||||
|
|
@ -363,6 +364,7 @@
|
|||
#define USB_PID_TVWAY_PLUS 0x0002
|
||||
#define USB_PID_SVEON_STV20 0xe39d
|
||||
#define USB_PID_SVEON_STV20_RTL2832U 0xd39d
|
||||
#define USB_PID_SVEON_STV21 0xd3b0
|
||||
#define USB_PID_SVEON_STV22 0xe401
|
||||
#define USB_PID_SVEON_STV22_IT9137 0xe411
|
||||
#define USB_PID_AZUREWAVE_AZ6027 0x3275
|
||||
|
|
|
|||
|
|
@ -96,10 +96,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open(
|
|||
* FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
|
||||
*/
|
||||
|
||||
#define DVB_FE_NO_EXIT 0
|
||||
#define DVB_FE_NORMAL_EXIT 1
|
||||
#define DVB_FE_DEVICE_REMOVED 2
|
||||
|
||||
static DEFINE_MUTEX(frontend_mutex);
|
||||
|
||||
struct dvb_frontend_private {
|
||||
|
|
@ -113,7 +109,6 @@ struct dvb_frontend_private {
|
|||
wait_queue_head_t wait_queue;
|
||||
struct task_struct *thread;
|
||||
unsigned long release_jiffies;
|
||||
unsigned int exit;
|
||||
unsigned int wakeup;
|
||||
fe_status_t status;
|
||||
unsigned long tune_mode_flags;
|
||||
|
|
@ -565,7 +560,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
|
|||
{
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
|
||||
if (fepriv->exit != DVB_FE_NO_EXIT)
|
||||
if (fe->exit != DVB_FE_NO_EXIT)
|
||||
return 1;
|
||||
|
||||
if (fepriv->dvbdev->writers == 1)
|
||||
|
|
@ -629,7 +624,7 @@ restart:
|
|||
/* got signal or quitting */
|
||||
if (!down_interruptible(&fepriv->sem))
|
||||
semheld = true;
|
||||
fepriv->exit = DVB_FE_NORMAL_EXIT;
|
||||
fe->exit = DVB_FE_NORMAL_EXIT;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -739,9 +734,9 @@ restart:
|
|||
|
||||
fepriv->thread = NULL;
|
||||
if (kthread_should_stop())
|
||||
fepriv->exit = DVB_FE_DEVICE_REMOVED;
|
||||
fe->exit = DVB_FE_DEVICE_REMOVED;
|
||||
else
|
||||
fepriv->exit = DVB_FE_NO_EXIT;
|
||||
fe->exit = DVB_FE_NO_EXIT;
|
||||
mb();
|
||||
|
||||
if (semheld)
|
||||
|
|
@ -756,7 +751,8 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
|
|||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
fepriv->exit = DVB_FE_NORMAL_EXIT;
|
||||
if (fe->exit != DVB_FE_DEVICE_REMOVED)
|
||||
fe->exit = DVB_FE_NORMAL_EXIT;
|
||||
mb();
|
||||
|
||||
if (!fepriv->thread)
|
||||
|
|
@ -826,7 +822,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
|
|||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
if (fepriv->thread) {
|
||||
if (fepriv->exit == DVB_FE_NO_EXIT)
|
||||
if (fe->exit == DVB_FE_NO_EXIT)
|
||||
return 0;
|
||||
else
|
||||
dvb_frontend_stop (fe);
|
||||
|
|
@ -838,7 +834,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
|
|||
return -EINTR;
|
||||
|
||||
fepriv->state = FESTATE_IDLE;
|
||||
fepriv->exit = DVB_FE_NO_EXIT;
|
||||
fe->exit = DVB_FE_NO_EXIT;
|
||||
fepriv->thread = NULL;
|
||||
mb();
|
||||
|
||||
|
|
@ -1906,7 +1902,7 @@ static int dvb_frontend_ioctl(struct file *file,
|
|||
if (down_interruptible(&fepriv->sem))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (fepriv->exit != DVB_FE_NO_EXIT) {
|
||||
if (fe->exit != DVB_FE_NO_EXIT) {
|
||||
up(&fepriv->sem);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
@ -2424,7 +2420,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
|||
int ret;
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
|
||||
if (fe->exit == DVB_FE_DEVICE_REMOVED)
|
||||
return -ENODEV;
|
||||
|
||||
if (adapter->mfe_shared) {
|
||||
|
|
@ -2529,7 +2525,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
|
|||
|
||||
if (dvbdev->users == -1) {
|
||||
wake_up(&fepriv->wait_queue);
|
||||
if (fepriv->exit != DVB_FE_NO_EXIT)
|
||||
if (fe->exit != DVB_FE_NO_EXIT)
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
if (fe->ops.ts_bus_ctrl)
|
||||
fe->ops.ts_bus_ctrl(fe, 0);
|
||||
|
|
@ -2572,12 +2568,14 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
|
|||
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
|
||||
fe->id);
|
||||
|
||||
fe->exit = DVB_FE_DEVICE_RESUME;
|
||||
if (fe->ops.init)
|
||||
ret = fe->ops.init(fe);
|
||||
|
||||
if (fe->ops.tuner_ops.init)
|
||||
ret = fe->ops.tuner_ops.init(fe);
|
||||
|
||||
fe->exit = DVB_FE_NO_EXIT;
|
||||
fepriv->state = FESTATE_RETUNE;
|
||||
dvb_frontend_wakeup(fe);
|
||||
|
||||
|
|
@ -2666,20 +2664,20 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
|
|||
|
||||
if (fe->ops.release_sec) {
|
||||
fe->ops.release_sec(fe);
|
||||
symbol_put_addr(fe->ops.release_sec);
|
||||
dvb_detach(fe->ops.release_sec);
|
||||
}
|
||||
if (fe->ops.tuner_ops.release) {
|
||||
fe->ops.tuner_ops.release(fe);
|
||||
symbol_put_addr(fe->ops.tuner_ops.release);
|
||||
dvb_detach(fe->ops.tuner_ops.release);
|
||||
}
|
||||
if (fe->ops.analog_ops.release) {
|
||||
fe->ops.analog_ops.release(fe);
|
||||
symbol_put_addr(fe->ops.analog_ops.release);
|
||||
dvb_detach(fe->ops.analog_ops.release);
|
||||
}
|
||||
ptr = (void*)fe->ops.release;
|
||||
if (ptr) {
|
||||
fe->ops.release(fe);
|
||||
symbol_put_addr(ptr);
|
||||
dvb_detach(ptr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -405,6 +405,11 @@ struct dtv_frontend_properties {
|
|||
struct dtv_fe_stats block_count;
|
||||
};
|
||||
|
||||
#define DVB_FE_NO_EXIT 0
|
||||
#define DVB_FE_NORMAL_EXIT 1
|
||||
#define DVB_FE_DEVICE_REMOVED 2
|
||||
#define DVB_FE_DEVICE_RESUME 3
|
||||
|
||||
struct dvb_frontend {
|
||||
struct dvb_frontend_ops ops;
|
||||
struct dvb_adapter *dvb;
|
||||
|
|
@ -418,6 +423,7 @@ struct dvb_frontend {
|
|||
#define DVB_FRONTEND_COMPONENT_DEMOD 1
|
||||
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
|
||||
int id;
|
||||
unsigned int exit;
|
||||
};
|
||||
|
||||
extern int dvb_register_frontend(struct dvb_adapter *dvb,
|
||||
|
|
|
|||
|
|
@ -136,11 +136,15 @@ extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
|
|||
__r; \
|
||||
})
|
||||
|
||||
#define dvb_detach(FUNC) symbol_put_addr(FUNC)
|
||||
|
||||
#else
|
||||
#define dvb_attach(FUNCTION, ARGS...) ({ \
|
||||
FUNCTION(ARGS); \
|
||||
})
|
||||
|
||||
#define dvb_detach(FUNC) {}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _DVBDEV_H_ */
|
||||
|
|
|
|||
|
|
@ -63,6 +63,15 @@ config DVB_TDA18271C2DD
|
|||
|
||||
Say Y when you want to support this tuner.
|
||||
|
||||
config DVB_SI2165
|
||||
tristate "Silicon Labs si2165 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A DVB-C/T demodulator.
|
||||
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "DVB-S (satellite) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
|
@ -446,6 +455,15 @@ config DVB_RTL2832
|
|||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_RTL2832_SDR
|
||||
tristate "Realtek RTL2832 SDR"
|
||||
depends on DVB_CORE && I2C && I2C_MUX && VIDEO_V4L2 && MEDIA_SDR_SUPPORT && USB
|
||||
select DVB_RTL2832
|
||||
select VIDEOBUF2_VMALLOC
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this SDR module.
|
||||
|
||||
config DVB_SI2168
|
||||
tristate "Silicon Labs Si2168"
|
||||
depends on DVB_CORE && I2C && I2C_MUX
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@
|
|||
ccflags-y += -I$(srctree)/drivers/media/dvb-core/
|
||||
ccflags-y += -I$(srctree)/drivers/media/tuners/
|
||||
|
||||
# FIXME: RTL2832 SDR driver uses power management directly from USB IF driver
|
||||
ifdef CONFIG_DVB_RTL2832_SDR
|
||||
ccflags-y += -I$(srctree)/drivers/media/usb/dvb-usb-v2
|
||||
endif
|
||||
|
||||
stb0899-objs := stb0899_drv.o stb0899_algo.o
|
||||
stv0900-objs := stv0900_core.o stv0900_sw.o
|
||||
drxd-objs := drxd_firm.o drxd_hard.o
|
||||
|
|
@ -100,10 +105,12 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
|
|||
obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
|
||||
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_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
|
||||
|
||||
|
|
|
|||
|
|
@ -470,7 +470,6 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe)
|
|||
break;
|
||||
default:
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ static void setup_vbi(struct au8522_state *state, int aud_input)
|
|||
|
||||
}
|
||||
|
||||
static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
|
||||
static void setup_decoder_defaults(struct au8522_state *state, bool is_svideo)
|
||||
{
|
||||
int i;
|
||||
int filter_coef_type;
|
||||
|
|
@ -237,13 +237,10 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
|
|||
/* Other decoder registers */
|
||||
au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
|
||||
|
||||
if (input_mode == 0x23) {
|
||||
/* S-Video input mapping */
|
||||
if (is_svideo)
|
||||
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
|
||||
} else {
|
||||
/* All other modes (CVBS/ATVRF etc.) */
|
||||
else
|
||||
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
|
||||
}
|
||||
|
||||
au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
|
||||
AU8522_TVDEC_PGA_REG012H_CVBS);
|
||||
|
|
@ -251,12 +248,23 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
|
|||
AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
|
||||
AU8522_TVDED_DBG_MODE_REG060H_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
|
||||
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
|
||||
AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
|
||||
|
||||
if (state->std == V4L2_STD_PAL_M) {
|
||||
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_AUTO);
|
||||
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
|
||||
AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M);
|
||||
} else {
|
||||
/* NTSC */
|
||||
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
|
||||
AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
|
||||
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
|
||||
AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
|
||||
}
|
||||
au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
|
||||
AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
|
||||
|
|
@ -275,8 +283,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
|
|||
AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
|
||||
AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
|
||||
if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
|
||||
input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
|
||||
if (is_svideo) {
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
|
||||
AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
|
||||
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
|
||||
|
|
@ -317,8 +324,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
|
|||
|
||||
setup_vbi(state, 0);
|
||||
|
||||
if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
|
||||
input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
|
||||
if (is_svideo) {
|
||||
/* Despite what the table says, for the HVR-950q we still need
|
||||
to be in CVBS mode for the S-Video input (reason unknown). */
|
||||
/* filter_coef_type = 3; */
|
||||
|
|
@ -346,7 +352,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
|
|||
au8522_writereg(state, AU8522_REG436H, 0x3c);
|
||||
}
|
||||
|
||||
static void au8522_setup_cvbs_mode(struct au8522_state *state)
|
||||
static void au8522_setup_cvbs_mode(struct au8522_state *state, u8 input_mode)
|
||||
{
|
||||
/* here we're going to try the pre-programmed route */
|
||||
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
|
||||
|
|
@ -358,16 +364,16 @@ static void au8522_setup_cvbs_mode(struct au8522_state *state)
|
|||
/* Enable clamping control */
|
||||
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
|
||||
|
||||
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
|
||||
AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
|
||||
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
|
||||
|
||||
setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
|
||||
setup_decoder_defaults(state, false);
|
||||
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
|
||||
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
|
||||
}
|
||||
|
||||
static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
|
||||
static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state,
|
||||
u8 input_mode)
|
||||
{
|
||||
/* here we're going to try the pre-programmed route */
|
||||
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
|
||||
|
|
@ -384,24 +390,22 @@ static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
|
|||
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
|
||||
|
||||
/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
|
||||
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
|
||||
AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
|
||||
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
|
||||
|
||||
setup_decoder_defaults(state,
|
||||
AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
|
||||
setup_decoder_defaults(state, false);
|
||||
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
|
||||
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
|
||||
}
|
||||
|
||||
static void au8522_setup_svideo_mode(struct au8522_state *state)
|
||||
static void au8522_setup_svideo_mode(struct au8522_state *state,
|
||||
u8 input_mode)
|
||||
{
|
||||
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
|
||||
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
|
||||
|
||||
/* Set input to Y on Channe1, C on Channel 3 */
|
||||
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
|
||||
AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
|
||||
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
|
||||
|
||||
/* PGA in automatic mode */
|
||||
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
|
||||
|
|
@ -409,8 +413,7 @@ static void au8522_setup_svideo_mode(struct au8522_state *state)
|
|||
/* Enable clamping control */
|
||||
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
|
||||
|
||||
setup_decoder_defaults(state,
|
||||
AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
|
||||
setup_decoder_defaults(state, true);
|
||||
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
|
||||
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
|
||||
|
|
@ -432,8 +435,9 @@ static void disable_audio_input(struct au8522_state *state)
|
|||
}
|
||||
|
||||
/* 0=disable, 1=SIF */
|
||||
static void set_audio_input(struct au8522_state *state, int aud_input)
|
||||
static void set_audio_input(struct au8522_state *state)
|
||||
{
|
||||
int aud_input = state->aud_input;
|
||||
int i;
|
||||
|
||||
/* Note that this function needs to be used in conjunction with setting
|
||||
|
|
@ -465,8 +469,9 @@ static void set_audio_input(struct au8522_state *state, int aud_input)
|
|||
au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
|
||||
msleep(150);
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
|
||||
msleep(1);
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
|
||||
msleep(10);
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
|
||||
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
|
||||
msleep(50);
|
||||
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
|
||||
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
|
||||
|
|
@ -539,58 +544,109 @@ static int au8522_s_register(struct v4l2_subdev *sd,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void au8522_video_set(struct au8522_state *state)
|
||||
{
|
||||
u8 input_mode;
|
||||
|
||||
au8522_writereg(state, 0xa4, 1 << 5);
|
||||
|
||||
switch (state->vid_input) {
|
||||
case AU8522_COMPOSITE_CH1:
|
||||
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH1;
|
||||
au8522_setup_cvbs_mode(state, input_mode);
|
||||
break;
|
||||
case AU8522_COMPOSITE_CH2:
|
||||
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH2;
|
||||
au8522_setup_cvbs_mode(state, input_mode);
|
||||
break;
|
||||
case AU8522_COMPOSITE_CH3:
|
||||
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH3;
|
||||
au8522_setup_cvbs_mode(state, input_mode);
|
||||
break;
|
||||
case AU8522_COMPOSITE_CH4:
|
||||
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4;
|
||||
au8522_setup_cvbs_mode(state, input_mode);
|
||||
break;
|
||||
case AU8522_SVIDEO_CH13:
|
||||
input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13;
|
||||
au8522_setup_svideo_mode(state, input_mode);
|
||||
break;
|
||||
case AU8522_SVIDEO_CH24:
|
||||
input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24;
|
||||
au8522_setup_svideo_mode(state, input_mode);
|
||||
break;
|
||||
default:
|
||||
case AU8522_COMPOSITE_CH4_SIF:
|
||||
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF;
|
||||
au8522_setup_cvbs_tuner_mode(state, input_mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct au8522_state *state = to_state(sd);
|
||||
|
||||
if (enable) {
|
||||
/*
|
||||
* Clear out any state associated with the digital side of the
|
||||
* chip, so that when it gets powered back up it won't think
|
||||
* that it is already tuned
|
||||
*/
|
||||
state->current_frequency = 0;
|
||||
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
|
||||
0x01);
|
||||
msleep(1);
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
|
||||
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
|
||||
msleep(10);
|
||||
|
||||
au8522_video_set(state);
|
||||
set_audio_input(state);
|
||||
|
||||
state->operational_mode = AU8522_ANALOG_MODE;
|
||||
} else {
|
||||
/* This does not completely power down the device
|
||||
(it only reduces it from around 140ma to 80ma) */
|
||||
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
|
||||
1 << 5);
|
||||
state->operational_mode = AU8522_SUSPEND_MODE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int au8522_reset(struct v4l2_subdev *sd, u32 val)
|
||||
{
|
||||
struct au8522_state *state = to_state(sd);
|
||||
|
||||
state->operational_mode = AU8522_ANALOG_MODE;
|
||||
|
||||
/* Clear out any state associated with the digital side of the
|
||||
chip, so that when it gets powered back up it won't think
|
||||
that it is already tuned */
|
||||
state->current_frequency = 0;
|
||||
|
||||
au8522_writereg(state, 0xa4, 1 << 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int au8522_s_video_routing(struct v4l2_subdev *sd,
|
||||
u32 input, u32 output, u32 config)
|
||||
{
|
||||
struct au8522_state *state = to_state(sd);
|
||||
|
||||
au8522_reset(sd, 0);
|
||||
|
||||
if (input == AU8522_COMPOSITE_CH1) {
|
||||
au8522_setup_cvbs_mode(state);
|
||||
} else if (input == AU8522_SVIDEO_CH13) {
|
||||
au8522_setup_svideo_mode(state);
|
||||
} else if (input == AU8522_COMPOSITE_CH4_SIF) {
|
||||
au8522_setup_cvbs_tuner_mode(state);
|
||||
} else {
|
||||
switch(input) {
|
||||
case AU8522_COMPOSITE_CH1:
|
||||
case AU8522_SVIDEO_CH13:
|
||||
case AU8522_COMPOSITE_CH4_SIF:
|
||||
state->vid_input = input;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "au8522 mode not currently supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (state->operational_mode == AU8522_ANALOG_MODE)
|
||||
au8522_video_set(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int au8522_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
|
||||
{
|
||||
struct au8522_state *state = to_state(sd);
|
||||
|
||||
if ((std & (V4L2_STD_PAL_M | V4L2_STD_NTSC_M)) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
state->std = std;
|
||||
|
||||
if (state->operational_mode == AU8522_ANALOG_MODE)
|
||||
au8522_video_set(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -598,7 +654,12 @@ static int au8522_s_audio_routing(struct v4l2_subdev *sd,
|
|||
u32 input, u32 output, u32 config)
|
||||
{
|
||||
struct au8522_state *state = to_state(sd);
|
||||
set_audio_input(state, input);
|
||||
|
||||
state->aud_input = input;
|
||||
|
||||
if (state->operational_mode == AU8522_ANALOG_MODE)
|
||||
set_audio_input(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -629,7 +690,6 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
|
|||
|
||||
static const struct v4l2_subdev_core_ops au8522_core_ops = {
|
||||
.log_status = v4l2_ctrl_subdev_log_status,
|
||||
.reset = au8522_reset,
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.g_register = au8522_g_register,
|
||||
.s_register = au8522_s_register,
|
||||
|
|
@ -647,6 +707,7 @@ static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
|
|||
static const struct v4l2_subdev_video_ops au8522_video_ops = {
|
||||
.s_routing = au8522_s_video_routing,
|
||||
.s_stream = au8522_s_stream,
|
||||
.s_std = au8522_s_std,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops au8522_ops = {
|
||||
|
|
@ -729,6 +790,7 @@ static int au8522_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
state->c = client;
|
||||
state->std = V4L2_STD_NTSC_M;
|
||||
state->vid_input = AU8522_COMPOSITE_CH1;
|
||||
state->aud_input = AU8522_AUDIO_NONE;
|
||||
state->id = 8522;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#define AU8522_ANALOG_MODE 0
|
||||
#define AU8522_DIGITAL_MODE 1
|
||||
#define AU8522_SUSPEND_MODE 2
|
||||
|
||||
struct au8522_state {
|
||||
struct i2c_client *c;
|
||||
|
|
@ -347,6 +348,7 @@ int au8522_led_ctrl(struct au8522_state *state, int led);
|
|||
/* Format control 2 */
|
||||
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_AUTODETECT 0x00
|
||||
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC 0x01
|
||||
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M 0x02
|
||||
|
||||
|
||||
#define AU8522_INPUT_CONTROL_REG081H_ATSC 0xC4
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@ struct cxd2820r_config {
|
|||
*/
|
||||
u8 ts_mode;
|
||||
|
||||
/* TS clock inverted.
|
||||
* Default: 0
|
||||
* Values: 0, 1
|
||||
*/
|
||||
bool ts_clock_inv;
|
||||
|
||||
/* IF AGC polarity.
|
||||
* Default: 0
|
||||
* Values: 0, 1
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
|
|||
{ 0x1008b, 0x07, 0xff },
|
||||
{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
|
||||
{ 0x10070, priv->cfg.ts_mode, 0xff },
|
||||
{ 0x10071, !priv->cfg.ts_clock_inv << 4, 0x10 },
|
||||
};
|
||||
|
||||
dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
|
|||
{ 0x00088, 0x01, 0xff },
|
||||
|
||||
{ 0x00070, priv->cfg.ts_mode, 0xff },
|
||||
{ 0x00071, !priv->cfg.ts_clock_inv << 4, 0x10 },
|
||||
{ 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 },
|
||||
{ 0x000a5, 0x00, 0x01 },
|
||||
{ 0x00082, 0x20, 0x60 },
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
|
|||
{ 0x02083, 0x0a, 0xff },
|
||||
{ 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 },
|
||||
{ 0x02070, priv->cfg.ts_mode, 0xff },
|
||||
{ 0x02071, !priv->cfg.ts_clock_inv << 6, 0x40 },
|
||||
{ 0x020b5, priv->cfg.spec_inv << 4, 0x10 },
|
||||
{ 0x02567, 0x07, 0x0f },
|
||||
{ 0x02569, 0x03, 0x03 },
|
||||
|
|
|
|||
|
|
@ -2557,10 +2557,19 @@ static int dib0090_set_params(struct dvb_frontend *fe)
|
|||
|
||||
do {
|
||||
ret = dib0090_tune(fe);
|
||||
if (ret != FE_CALLBACK_TIME_NEVER)
|
||||
msleep(ret / 10);
|
||||
else
|
||||
if (ret == FE_CALLBACK_TIME_NEVER)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Despite dib0090_tune returns time at a 0.1 ms range,
|
||||
* the actual sleep time depends on CONFIG_HZ. The worse case
|
||||
* is when CONFIG_HZ=100. In such case, the minimum granularity
|
||||
* is 10ms. On some real field tests, the tuner sometimes don't
|
||||
* lock when this timer is lower than 10ms. So, enforce a 10ms
|
||||
* granularity and use usleep_range() instead of msleep().
|
||||
*/
|
||||
ret = 10 * (ret + 99)/100;
|
||||
usleep_range(ret * 1000, (ret + 1) * 1000);
|
||||
} while (state->tune_state != CT_TUNER_STOP);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1041,10 +1041,7 @@ static int dib7000m_tune(struct dvb_frontend *demod)
|
|||
u16 value;
|
||||
|
||||
// we are already tuned - just resuming from suspend
|
||||
if (ch != NULL)
|
||||
dib7000m_set_channel(state, ch, 0);
|
||||
else
|
||||
return -EINVAL;
|
||||
dib7000m_set_channel(state, ch, 0);
|
||||
|
||||
// restart demod
|
||||
ret |= dib7000m_write_word(state, 898, 0x4000);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "dvb_math.h"
|
||||
#include "dvb_frontend.h"
|
||||
|
|
@ -72,6 +73,12 @@ struct dib7000p_state {
|
|||
struct mutex i2c_buffer_lock;
|
||||
|
||||
u8 input_mode_mpeg;
|
||||
|
||||
/* for DVBv5 stats */
|
||||
s64 old_ucb;
|
||||
unsigned long per_jiffies_stats;
|
||||
unsigned long ber_jiffies_stats;
|
||||
unsigned long get_stats_time;
|
||||
};
|
||||
|
||||
enum dib7000p_power_mode {
|
||||
|
|
@ -401,7 +408,7 @@ static int dib7000p_sad_calib(struct dib7000p_state *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
|
||||
static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
|
||||
{
|
||||
struct dib7000p_state *state = demod->demodulator_priv;
|
||||
if (value > 4095)
|
||||
|
|
@ -409,9 +416,8 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
|
|||
state->wbd_ref = value;
|
||||
return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_set_wbd_ref);
|
||||
|
||||
int dib7000p_get_agc_values(struct dvb_frontend *fe,
|
||||
static int dib7000p_get_agc_values(struct dvb_frontend *fe,
|
||||
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
|
|
@ -427,14 +433,12 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_get_agc_values);
|
||||
|
||||
int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
|
||||
static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
return dib7000p_write_word(state, 108, v);
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_set_agc1_min);
|
||||
|
||||
static void dib7000p_reset_pll(struct dib7000p_state *state)
|
||||
{
|
||||
|
|
@ -478,7 +482,7 @@ static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
|
|||
return internal;
|
||||
}
|
||||
|
||||
int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
|
||||
static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
|
||||
|
|
@ -513,7 +517,6 @@ int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config
|
|||
}
|
||||
return -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_update_pll);
|
||||
|
||||
static int dib7000p_reset_gpio(struct dib7000p_state *st)
|
||||
{
|
||||
|
|
@ -546,12 +549,11 @@ static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
|
||||
static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
|
||||
{
|
||||
struct dib7000p_state *state = demod->demodulator_priv;
|
||||
return dib7000p_cfg_gpio(state, num, dir, val);
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_set_gpio);
|
||||
|
||||
static u16 dib7000p_defaults[] = {
|
||||
// auto search configuration
|
||||
|
|
@ -636,6 +638,8 @@ static u16 dib7000p_defaults[] = {
|
|||
0,
|
||||
};
|
||||
|
||||
static void dib7000p_reset_stats(struct dvb_frontend *fe);
|
||||
|
||||
static int dib7000p_demod_reset(struct dib7000p_state *state)
|
||||
{
|
||||
dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
|
||||
|
|
@ -934,7 +938,7 @@ static void dib7000p_update_timf(struct dib7000p_state *state)
|
|||
|
||||
}
|
||||
|
||||
u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
|
||||
static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
switch (op) {
|
||||
|
|
@ -950,7 +954,6 @@ u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
|
|||
dib7000p_set_bandwidth(state, state->current_bandwidth);
|
||||
return state->timf;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_ctrl_timf);
|
||||
|
||||
static void dib7000p_set_channel(struct dib7000p_state *state,
|
||||
struct dtv_frontend_properties *ch, u8 seq)
|
||||
|
|
@ -1360,6 +1363,9 @@ static int dib7000p_tune(struct dvb_frontend *demod)
|
|||
dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
|
||||
|
||||
dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
|
||||
|
||||
dib7000p_reset_stats(demod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1552,6 +1558,8 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int dib7000p_get_stats(struct dvb_frontend *fe, fe_status_t stat);
|
||||
|
||||
static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
|
|
@ -1570,6 +1578,8 @@ static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
|
|||
if ((lock & 0x0038) == 0x38)
|
||||
*stat |= FE_HAS_LOCK;
|
||||
|
||||
dib7000p_get_stats(fe, *stat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1595,7 +1605,7 @@ static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
|
||||
static u32 dib7000p_get_snr(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
u16 val;
|
||||
|
|
@ -1625,10 +1635,351 @@ static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
|
|||
else
|
||||
result -= intlog10(2) * 10 * noise_exp - 100;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int dib7000p_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
{
|
||||
u32 result;
|
||||
|
||||
result = dib7000p_get_snr(fe);
|
||||
|
||||
*snr = result / ((1 << 24) / 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dib7000p_reset_stats(struct dvb_frontend *demod)
|
||||
{
|
||||
struct dib7000p_state *state = demod->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
|
||||
u32 ucb;
|
||||
|
||||
memset(&c->strength, 0, sizeof(c->strength));
|
||||
memset(&c->cnr, 0, sizeof(c->cnr));
|
||||
memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
|
||||
memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
|
||||
memset(&c->block_error, 0, sizeof(c->block_error));
|
||||
|
||||
c->strength.len = 1;
|
||||
c->cnr.len = 1;
|
||||
c->block_error.len = 1;
|
||||
c->block_count.len = 1;
|
||||
c->post_bit_error.len = 1;
|
||||
c->post_bit_count.len = 1;
|
||||
|
||||
c->strength.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
c->strength.stat[0].uvalue = 0;
|
||||
|
||||
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
|
||||
dib7000p_read_unc_blocks(demod, &ucb);
|
||||
|
||||
state->old_ucb = ucb;
|
||||
state->ber_jiffies_stats = 0;
|
||||
state->per_jiffies_stats = 0;
|
||||
}
|
||||
|
||||
struct linear_segments {
|
||||
unsigned x;
|
||||
signed y;
|
||||
};
|
||||
|
||||
/*
|
||||
* Table to estimate signal strength in dBm.
|
||||
* This table should be empirically determinated by measuring the signal
|
||||
* strength generated by a RF generator directly connected into
|
||||
* a device.
|
||||
* This table was determinated by measuring the signal strength generated
|
||||
* by a DTA-2111 RF generator directly connected into a dib7000p device
|
||||
* (a Hauppauge Nova-TD stick), using a good quality 3 meters length
|
||||
* RC6 cable and good RC6 connectors, connected directly to antenna 1.
|
||||
* As the minimum output power of DTA-2111 is -31dBm, a 16 dBm attenuator
|
||||
* were used, for the lower power values.
|
||||
* The real value can actually be on other devices, or even at the
|
||||
* second antena input, depending on several factors, like if LNA
|
||||
* is enabled or not, if diversity is enabled, type of connectors, etc.
|
||||
* Yet, it is better to use this measure in dB than a random non-linear
|
||||
* percentage value, especially for antenna adjustments.
|
||||
* On my tests, the precision of the measure using this table is about
|
||||
* 0.5 dB, with sounds reasonable enough to adjust antennas.
|
||||
*/
|
||||
#define DB_OFFSET 131000
|
||||
|
||||
static struct linear_segments strength_to_db_table[] = {
|
||||
{ 63630, DB_OFFSET - 20500},
|
||||
{ 62273, DB_OFFSET - 21000},
|
||||
{ 60162, DB_OFFSET - 22000},
|
||||
{ 58730, DB_OFFSET - 23000},
|
||||
{ 58294, DB_OFFSET - 24000},
|
||||
{ 57778, DB_OFFSET - 25000},
|
||||
{ 57320, DB_OFFSET - 26000},
|
||||
{ 56779, DB_OFFSET - 27000},
|
||||
{ 56293, DB_OFFSET - 28000},
|
||||
{ 55724, DB_OFFSET - 29000},
|
||||
{ 55145, DB_OFFSET - 30000},
|
||||
{ 54680, DB_OFFSET - 31000},
|
||||
{ 54293, DB_OFFSET - 32000},
|
||||
{ 53813, DB_OFFSET - 33000},
|
||||
{ 53427, DB_OFFSET - 34000},
|
||||
{ 52981, DB_OFFSET - 35000},
|
||||
|
||||
{ 52636, DB_OFFSET - 36000},
|
||||
{ 52014, DB_OFFSET - 37000},
|
||||
{ 51674, DB_OFFSET - 38000},
|
||||
{ 50692, DB_OFFSET - 39000},
|
||||
{ 49824, DB_OFFSET - 40000},
|
||||
{ 49052, DB_OFFSET - 41000},
|
||||
{ 48436, DB_OFFSET - 42000},
|
||||
{ 47836, DB_OFFSET - 43000},
|
||||
{ 47368, DB_OFFSET - 44000},
|
||||
{ 46468, DB_OFFSET - 45000},
|
||||
{ 45597, DB_OFFSET - 46000},
|
||||
{ 44586, DB_OFFSET - 47000},
|
||||
{ 43667, DB_OFFSET - 48000},
|
||||
{ 42673, DB_OFFSET - 49000},
|
||||
{ 41816, DB_OFFSET - 50000},
|
||||
{ 40876, DB_OFFSET - 51000},
|
||||
{ 0, 0},
|
||||
};
|
||||
|
||||
static u32 interpolate_value(u32 value, struct linear_segments *segments,
|
||||
unsigned len)
|
||||
{
|
||||
u64 tmp64;
|
||||
u32 dx;
|
||||
s32 dy;
|
||||
int i, ret;
|
||||
|
||||
if (value >= segments[0].x)
|
||||
return segments[0].y;
|
||||
if (value < segments[len-1].x)
|
||||
return segments[len-1].y;
|
||||
|
||||
for (i = 1; i < len - 1; i++) {
|
||||
/* If value is identical, no need to interpolate */
|
||||
if (value == segments[i].x)
|
||||
return segments[i].y;
|
||||
if (value > segments[i].x)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Linear interpolation between the two (x,y) points */
|
||||
dy = segments[i - 1].y - segments[i].y;
|
||||
dx = segments[i - 1].x - segments[i].x;
|
||||
|
||||
tmp64 = value - segments[i].x;
|
||||
tmp64 *= dy;
|
||||
do_div(tmp64, dx);
|
||||
ret = segments[i].y + tmp64;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: may require changes - this one was borrowed from dib8000 */
|
||||
static u32 dib7000p_get_time_us(struct dvb_frontend *demod, int layer)
|
||||
{
|
||||
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
|
||||
u64 time_us, tmp64;
|
||||
u32 tmp, denom;
|
||||
int guard, rate_num, rate_denum = 1, bits_per_symbol;
|
||||
int interleaving = 0, fft_div;
|
||||
|
||||
switch (c->guard_interval) {
|
||||
case GUARD_INTERVAL_1_4:
|
||||
guard = 4;
|
||||
break;
|
||||
case GUARD_INTERVAL_1_8:
|
||||
guard = 8;
|
||||
break;
|
||||
case GUARD_INTERVAL_1_16:
|
||||
guard = 16;
|
||||
break;
|
||||
default:
|
||||
case GUARD_INTERVAL_1_32:
|
||||
guard = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c->transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K:
|
||||
fft_div = 4;
|
||||
break;
|
||||
case TRANSMISSION_MODE_4K:
|
||||
fft_div = 2;
|
||||
break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K:
|
||||
fft_div = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c->modulation) {
|
||||
case DQPSK:
|
||||
case QPSK:
|
||||
bits_per_symbol = 2;
|
||||
break;
|
||||
case QAM_16:
|
||||
bits_per_symbol = 4;
|
||||
break;
|
||||
default:
|
||||
case QAM_64:
|
||||
bits_per_symbol = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((c->hierarchy == 0 || 1 == 1) ? c->code_rate_HP : c->code_rate_LP) {
|
||||
case FEC_1_2:
|
||||
rate_num = 1;
|
||||
rate_denum = 2;
|
||||
break;
|
||||
case FEC_2_3:
|
||||
rate_num = 2;
|
||||
rate_denum = 3;
|
||||
break;
|
||||
case FEC_3_4:
|
||||
rate_num = 3;
|
||||
rate_denum = 4;
|
||||
break;
|
||||
case FEC_5_6:
|
||||
rate_num = 5;
|
||||
rate_denum = 6;
|
||||
break;
|
||||
default:
|
||||
case FEC_7_8:
|
||||
rate_num = 7;
|
||||
rate_denum = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
interleaving = interleaving;
|
||||
|
||||
denom = bits_per_symbol * rate_num * fft_div * 384;
|
||||
|
||||
/* If calculus gets wrong, wait for 1s for the next stats */
|
||||
if (!denom)
|
||||
return 0;
|
||||
|
||||
/* Estimate the period for the total bit rate */
|
||||
time_us = rate_denum * (1008 * 1562500L);
|
||||
tmp64 = time_us;
|
||||
do_div(tmp64, guard);
|
||||
time_us = time_us + tmp64;
|
||||
time_us += denom / 2;
|
||||
do_div(time_us, denom);
|
||||
|
||||
tmp = 1008 * 96 * interleaving;
|
||||
time_us += tmp + tmp / guard;
|
||||
|
||||
return time_us;
|
||||
}
|
||||
|
||||
static int dib7000p_get_stats(struct dvb_frontend *demod, fe_status_t stat)
|
||||
{
|
||||
struct dib7000p_state *state = demod->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
|
||||
int i;
|
||||
int show_per_stats = 0;
|
||||
u32 time_us = 0, val, snr;
|
||||
u64 blocks, ucb;
|
||||
s32 db;
|
||||
u16 strength;
|
||||
|
||||
/* Get Signal strength */
|
||||
dib7000p_read_signal_strength(demod, &strength);
|
||||
val = strength;
|
||||
db = interpolate_value(val,
|
||||
strength_to_db_table,
|
||||
ARRAY_SIZE(strength_to_db_table)) - DB_OFFSET;
|
||||
c->strength.stat[0].svalue = db;
|
||||
|
||||
/* UCB/BER/CNR measures require lock */
|
||||
if (!(stat & FE_HAS_LOCK)) {
|
||||
c->cnr.len = 1;
|
||||
c->block_count.len = 1;
|
||||
c->block_error.len = 1;
|
||||
c->post_bit_error.len = 1;
|
||||
c->post_bit_count.len = 1;
|
||||
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if time for stats was elapsed */
|
||||
if (time_after(jiffies, state->per_jiffies_stats)) {
|
||||
state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
|
||||
|
||||
/* Get SNR */
|
||||
snr = dib7000p_get_snr(demod);
|
||||
if (snr)
|
||||
snr = (1000L * snr) >> 24;
|
||||
else
|
||||
snr = 0;
|
||||
c->cnr.stat[0].svalue = snr;
|
||||
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
|
||||
/* Get UCB measures */
|
||||
dib7000p_read_unc_blocks(demod, &val);
|
||||
ucb = val - state->old_ucb;
|
||||
if (val < state->old_ucb)
|
||||
ucb += 0x100000000LL;
|
||||
|
||||
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
|
||||
c->block_error.stat[0].uvalue = ucb;
|
||||
|
||||
/* Estimate the number of packets based on bitrate */
|
||||
if (!time_us)
|
||||
time_us = dib7000p_get_time_us(demod, -1);
|
||||
|
||||
if (time_us) {
|
||||
blocks = 1250000ULL * 1000000ULL;
|
||||
do_div(blocks, time_us * 8 * 204);
|
||||
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
|
||||
c->block_count.stat[0].uvalue += blocks;
|
||||
}
|
||||
|
||||
show_per_stats = 1;
|
||||
}
|
||||
|
||||
/* Get post-BER measures */
|
||||
if (time_after(jiffies, state->ber_jiffies_stats)) {
|
||||
time_us = dib7000p_get_time_us(demod, -1);
|
||||
state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
|
||||
|
||||
dprintk("Next all layers stats available in %u us.", time_us);
|
||||
|
||||
dib7000p_read_ber(demod, &val);
|
||||
c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
|
||||
c->post_bit_error.stat[0].uvalue += val;
|
||||
|
||||
c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
|
||||
c->post_bit_count.stat[0].uvalue += 100000000;
|
||||
}
|
||||
|
||||
/* Get PER measures */
|
||||
if (show_per_stats) {
|
||||
dib7000p_read_unc_blocks(demod, &val);
|
||||
|
||||
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
|
||||
c->block_error.stat[0].uvalue += val;
|
||||
|
||||
time_us = dib7000p_get_time_us(demod, i);
|
||||
if (time_us) {
|
||||
blocks = 1250000ULL * 1000000ULL;
|
||||
do_div(blocks, time_us * 8 * 204);
|
||||
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
|
||||
c->block_count.stat[0].uvalue += blocks;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
|
||||
{
|
||||
tune->min_delay_ms = 1000;
|
||||
|
|
@ -1643,7 +1994,7 @@ static void dib7000p_release(struct dvb_frontend *demod)
|
|||
kfree(st);
|
||||
}
|
||||
|
||||
int dib7000pc_detection(struct i2c_adapter *i2c_adap)
|
||||
static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
|
||||
{
|
||||
u8 *tx, *rx;
|
||||
struct i2c_msg msg[2] = {
|
||||
|
|
@ -1688,16 +2039,14 @@ rx_memory_error:
|
|||
kfree(tx);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000pc_detection);
|
||||
|
||||
struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
|
||||
static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
|
||||
{
|
||||
struct dib7000p_state *st = demod->demodulator_priv;
|
||||
return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_get_i2c_master);
|
||||
|
||||
int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
|
||||
static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
u16 val = dib7000p_read_word(state, 235) & 0xffef;
|
||||
|
|
@ -1705,17 +2054,15 @@ int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
|
|||
dprintk("PID filter enabled %d", onoff);
|
||||
return dib7000p_write_word(state, 235, val);
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
|
||||
|
||||
int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
|
||||
static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
|
||||
return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_pid_filter);
|
||||
|
||||
int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
|
||||
static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
|
||||
{
|
||||
struct dib7000p_state *dpst;
|
||||
int k = 0;
|
||||
|
|
@ -1774,7 +2121,6 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
|
|||
kfree(dpst);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_i2c_enumeration);
|
||||
|
||||
static const s32 lut_1000ln_mant[] = {
|
||||
6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
|
||||
|
|
@ -2032,12 +2378,11 @@ static struct i2c_algorithm dib7090_tuner_xfer_algo = {
|
|||
.functionality = dib7000p_i2c_func,
|
||||
};
|
||||
|
||||
struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
|
||||
static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dib7000p_state *st = fe->demodulator_priv;
|
||||
return &st->dib7090_tuner_adap;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7090_get_i2c_tuner);
|
||||
|
||||
static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
|
||||
{
|
||||
|
|
@ -2329,7 +2674,7 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
|
||||
static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
u16 en_cur_state;
|
||||
|
|
@ -2352,15 +2697,13 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7090_tuner_sleep);
|
||||
|
||||
int dib7090_get_adc_power(struct dvb_frontend *fe)
|
||||
static int dib7090_get_adc_power(struct dvb_frontend *fe)
|
||||
{
|
||||
return dib7000p_get_adc_power(fe);
|
||||
}
|
||||
EXPORT_SYMBOL(dib7090_get_adc_power);
|
||||
|
||||
int dib7090_slave_reset(struct dvb_frontend *fe)
|
||||
static int dib7090_slave_reset(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dib7000p_state *state = fe->demodulator_priv;
|
||||
u16 reg;
|
||||
|
|
@ -2371,10 +2714,9 @@ int dib7090_slave_reset(struct dvb_frontend *fe)
|
|||
dib7000p_write_word(state, 1032, 0xffff);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7090_slave_reset);
|
||||
|
||||
static struct dvb_frontend_ops dib7000p_ops;
|
||||
struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
|
||||
static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
|
||||
{
|
||||
struct dvb_frontend *demod;
|
||||
struct dib7000p_state *st;
|
||||
|
|
@ -2423,6 +2765,8 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
|
|||
|
||||
dib7000p_demod_reset(st);
|
||||
|
||||
dib7000p_reset_stats(demod);
|
||||
|
||||
if (st->version == SOC7090) {
|
||||
dib7090_set_output_mode(demod, st->cfg.output_mode);
|
||||
dib7090_set_diversity_in(demod, 0);
|
||||
|
|
@ -2434,6 +2778,31 @@ error:
|
|||
kfree(st);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *dib7000p_attach(struct dib7000p_ops *ops)
|
||||
{
|
||||
if (!ops)
|
||||
return NULL;
|
||||
|
||||
ops->slave_reset = dib7090_slave_reset;
|
||||
ops->get_adc_power = dib7090_get_adc_power;
|
||||
ops->dib7000pc_detection = dib7000pc_detection;
|
||||
ops->get_i2c_tuner = dib7090_get_i2c_tuner;
|
||||
ops->tuner_sleep = dib7090_tuner_sleep;
|
||||
ops->init = dib7000p_init;
|
||||
ops->set_agc1_min = dib7000p_set_agc1_min;
|
||||
ops->set_gpio = dib7000p_set_gpio;
|
||||
ops->i2c_enumeration = dib7000p_i2c_enumeration;
|
||||
ops->pid_filter = dib7000p_pid_filter;
|
||||
ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl;
|
||||
ops->get_i2c_master = dib7000p_get_i2c_master;
|
||||
ops->update_pll = dib7000p_update_pll;
|
||||
ops->ctrl_timf = dib7000p_ctrl_timf;
|
||||
ops->get_agc_values = dib7000p_get_agc_values;
|
||||
ops->set_wbd_ref = dib7000p_set_wbd_ref;
|
||||
|
||||
return ops;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000p_attach);
|
||||
|
||||
static struct dvb_frontend_ops dib7000p_ops = {
|
||||
|
|
|
|||
|
|
@ -46,121 +46,34 @@ struct dib7000p_config {
|
|||
|
||||
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_DIB7000P)
|
||||
extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
|
||||
extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
|
||||
extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
|
||||
extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
|
||||
extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
|
||||
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
|
||||
extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
|
||||
extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
|
||||
extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
|
||||
extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
|
||||
extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
|
||||
extern int dib7090_get_adc_power(struct dvb_frontend *fe);
|
||||
extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
|
||||
extern int dib7090_slave_reset(struct dvb_frontend *fe);
|
||||
extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
|
||||
struct dib7000p_ops {
|
||||
int (*set_wbd_ref)(struct dvb_frontend *demod, u16 value);
|
||||
int (*get_agc_values)(struct dvb_frontend *fe,
|
||||
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
|
||||
extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v);
|
||||
int (*set_agc1_min)(struct dvb_frontend *fe, u16 v);
|
||||
int (*update_pll)(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
|
||||
int (*set_gpio)(struct dvb_frontend *demod, u8 num, u8 dir, u8 val);
|
||||
u32 (*ctrl_timf)(struct dvb_frontend *fe, u8 op, u32 timf);
|
||||
int (*dib7000pc_detection)(struct i2c_adapter *i2c_adap);
|
||||
struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating);
|
||||
int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
|
||||
int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
|
||||
int (*i2c_enumeration)(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
|
||||
struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
|
||||
int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
|
||||
int (*get_adc_power)(struct dvb_frontend *fe);
|
||||
int (*slave_reset)(struct dvb_frontend *fe);
|
||||
struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_DIB7000P)
|
||||
void *dib7000p_attach(struct dib7000p_ops *ops);
|
||||
#else
|
||||
static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
|
||||
static inline void *dib7000p_attach(struct dib7000p_ops *ops)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int dib7090_slave_reset(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
|
||||
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -39,134 +39,34 @@ struct dib8000_config {
|
|||
|
||||
#define DEFAULT_DIB8000_I2C_ADDRESS 18
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_DIB8000)
|
||||
extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
|
||||
extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
|
||||
|
||||
extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
|
||||
u8 default_addr, u8 first_addr, u8 is_dib8096p);
|
||||
|
||||
extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
|
||||
extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
|
||||
extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
|
||||
extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
|
||||
extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
|
||||
extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
|
||||
extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
|
||||
extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
|
||||
extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
|
||||
extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
|
||||
extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
|
||||
extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
|
||||
uint8_t op, uint32_t timf);
|
||||
extern int dib8000_update_pll(struct dvb_frontend *fe,
|
||||
struct dib8000_ops {
|
||||
int (*set_wbd_ref)(struct dvb_frontend *fe, u16 value);
|
||||
int (*update_pll)(struct dvb_frontend *fe,
|
||||
struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
|
||||
extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
|
||||
extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
|
||||
extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
|
||||
int (*set_gpio)(struct dvb_frontend *fe, u8 num, u8 dir, u8 val);
|
||||
void (*pwm_agc_reset)(struct dvb_frontend *fe);
|
||||
struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
|
||||
int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
|
||||
s32 (*get_adc_power)(struct dvb_frontend *fe, u8 mode);
|
||||
int (*get_dc_power)(struct dvb_frontend *fe, u8 IQ);
|
||||
u32 (*ctrl_timf)(struct dvb_frontend *fe, uint8_t op, uint32_t timf);
|
||||
enum frontend_tune_state (*get_tune_state)(struct dvb_frontend *fe);
|
||||
int (*set_tune_state)(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
|
||||
int (*set_slave_frontend)(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
|
||||
int (*remove_slave_frontend)(struct dvb_frontend *fe);
|
||||
struct dvb_frontend *(*get_slave_frontend)(struct dvb_frontend *fe, int slave_index);
|
||||
int (*i2c_enumeration)(struct i2c_adapter *host, int no_of_demods,
|
||||
u8 default_addr, u8 first_addr, u8 is_dib8096p);
|
||||
struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating);
|
||||
int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
|
||||
int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
|
||||
struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_DIB8000)
|
||||
void *dib8000_attach(struct dib8000_ops *ops);
|
||||
#else
|
||||
static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
|
||||
int no_of_demods, u8 default_addr, u8 first_addr,
|
||||
u8 is_dib8096p)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return CT_SHUTDOWN;
|
||||
}
|
||||
static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
}
|
||||
static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
|
||||
uint8_t op, uint32_t timf)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
static inline int dib8000_update_pll(struct dvb_frontend *fe,
|
||||
struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
|
||||
static inline int dib8000_attach(struct dib8000_ops *ops)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -1040,13 +1040,18 @@ static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 addres
|
|||
if (address >= 1024 || !state->platform.risc.fw_is_running)
|
||||
return -EINVAL;
|
||||
|
||||
if (len > 18)
|
||||
return -EINVAL;
|
||||
|
||||
/* dprintk( "APB access thru wr fw %d %x", address, attribute); */
|
||||
|
||||
mb[0] = (unsigned short)address;
|
||||
for (i = 0; i < len && i < 20; i += 2)
|
||||
mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
|
||||
mb[0] = (u16)address;
|
||||
for (i = 0; i + 1 < len; i += 2)
|
||||
mb[1 + i / 2] = b[i] << 8 | b[i + 1];
|
||||
if (len & 1)
|
||||
mb[1 + len / 2] = b[len - 1] << 8;
|
||||
|
||||
dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
|
||||
dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, (3 + len) / 2, attribute);
|
||||
return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2159,7 +2159,7 @@ int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr,
|
|||
return 0;
|
||||
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2252,7 +2252,7 @@ static int hi_cfg_command(const struct drx_demod_instance *demod)
|
|||
return 0;
|
||||
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2363,7 +2363,7 @@ hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16
|
|||
/* if ( powerdown_cmd == true ) */
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2434,7 +2434,7 @@ static int init_hi(const struct drx_demod_instance *demod)
|
|||
return 0;
|
||||
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -2650,7 +2650,7 @@ static int get_device_capabilities(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3338,7 +3338,7 @@ ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_o
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
@ -3421,7 +3421,7 @@ static int set_mpegtei_handling(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
@ -3464,7 +3464,7 @@ static int bit_reverse_mpeg_output(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
@ -3508,7 +3508,7 @@ static int set_mpeg_start_width(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
@ -3652,7 +3652,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3854,7 +3854,7 @@ ctrl_uio_write(struct drx_demod_instance *demod, struct drxuio_data *uio_data)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
@ -3969,7 +3969,7 @@ static int smart_ant_init(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd)
|
||||
|
|
@ -4109,7 +4109,7 @@ static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd
|
|||
return 0;
|
||||
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4178,7 +4178,7 @@ int drxj_dap_scu_atomic_read_write_block(struct i2c_device_addr *dev_addr, u32 a
|
|||
return 0;
|
||||
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -4290,7 +4290,7 @@ static int adc_sync_measurement(struct drx_demod_instance *demod, u16 *count)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4349,7 +4349,7 @@ static int adc_synchronization(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -4734,7 +4734,7 @@ static int init_agc(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4831,7 +4831,7 @@ set_frequency(struct drx_demod_instance *demod,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4879,7 +4879,7 @@ static int get_acc_pkt_err(struct drx_demod_instance *demod, u16 *packet_err)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -5097,7 +5097,7 @@ set_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5326,7 +5326,7 @@ set_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5362,7 +5362,7 @@ static int set_iqm_af(struct drx_demod_instance *demod, bool active)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -5470,7 +5470,7 @@ static int power_down_vsb(struct drx_demod_instance *demod, bool primary)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5686,7 +5686,7 @@ static int set_vsb_leak_n_gain(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6192,7 +6192,7 @@ static int set_vsb(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6231,7 +6231,7 @@ static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6276,7 +6276,7 @@ static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6321,7 +6321,7 @@ static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -6434,7 +6434,7 @@ static int power_down_qam(struct drx_demod_instance *demod, bool primary)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -6646,7 +6646,7 @@ set_qam_measurement(struct drx_demod_instance *demod,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -6881,7 +6881,7 @@ static int set_qam16(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -7116,7 +7116,7 @@ static int set_qam32(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -7351,7 +7351,7 @@ static int set_qam64(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -7586,7 +7586,7 @@ static int set_qam128(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -7821,7 +7821,7 @@ static int set_qam256(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -8650,7 +8650,7 @@ set_qam(struct drx_demod_instance *demod,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -8831,7 +8831,7 @@ static int qam_flip_spec(struct drx_demod_instance *demod, struct drx_channel *c
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -8984,7 +8984,7 @@ qam64auto(struct drx_demod_instance *demod,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -9068,7 +9068,7 @@ qam256auto(struct drx_demod_instance *demod,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -9273,7 +9273,7 @@ rw_error:
|
|||
/* restore starting value */
|
||||
if (auto_flag)
|
||||
channel->constellation = DRX_CONSTELLATION_AUTO;
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -9344,7 +9344,7 @@ get_qamrs_err_count(struct i2c_device_addr *dev_addr,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -9425,8 +9425,8 @@ static int get_sig_strength(struct drx_demod_instance *demod, u16 *sig_strength)
|
|||
*sig_strength = 0;
|
||||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
rw_error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -9643,7 +9643,7 @@ rw_error:
|
|||
p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* #ifndef DRXJ_VSB_ONLY */
|
||||
|
|
@ -9810,7 +9810,7 @@ power_down_atv(struct drx_demod_instance *demod, enum drx_standard standard, boo
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -9840,7 +9840,7 @@ static int power_down_aud(struct drx_demod_instance *demod)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -9874,7 +9874,7 @@ static int set_orx_nsu_aox(struct drx_demod_instance *demod, bool active)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -10398,7 +10398,7 @@ static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_par
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -10638,7 +10638,7 @@ ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel)
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
|
|
@ -10756,7 +10756,7 @@ ctrl_sig_quality(struct drx_demod_instance *demod,
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -10844,7 +10844,7 @@ ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_st
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -10941,7 +10941,7 @@ ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
|
|||
rw_error:
|
||||
/* Don't know what the standard is now ... try again */
|
||||
ext_attr->standard = DRX_STANDARD_UNKNOWN;
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -11222,7 +11222,7 @@ ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -11303,7 +11303,7 @@ ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain
|
|||
|
||||
return 0;
|
||||
rw_error:
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -11315,6 +11315,7 @@ rw_error:
|
|||
static int drx_ctrl_u_code(struct drx_demod_instance *demod,
|
||||
struct drxu_code_info *mc_info,
|
||||
enum drxu_code_action action);
|
||||
static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state);
|
||||
|
||||
/**
|
||||
* \fn drxj_open()
|
||||
|
|
@ -11527,10 +11528,11 @@ static int drxj_open(struct drx_demod_instance *demod)
|
|||
ext_attr->aud_data = drxj_default_aud_data_g;
|
||||
|
||||
demod->my_common_attr->is_opened = true;
|
||||
drxj_set_lna_state(demod, false);
|
||||
return 0;
|
||||
rw_error:
|
||||
common_attr->is_opened = false;
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
|
|
@ -11578,7 +11580,7 @@ static int drxj_close(struct drx_demod_instance *demod)
|
|||
rw_error:
|
||||
DRX_ATTR_ISOPENED(demod) = false;
|
||||
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -11890,6 +11892,33 @@ release:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* caller is expeced to check if lna is supported before enabling */
|
||||
static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state)
|
||||
{
|
||||
struct drxuio_cfg uio_cfg;
|
||||
struct drxuio_data uio_data;
|
||||
int result;
|
||||
|
||||
uio_cfg.uio = DRX_UIO1;
|
||||
uio_cfg.mode = DRX_UIO_MODE_READWRITE;
|
||||
/* Configure user-I/O #3: enable read/write */
|
||||
result = ctrl_set_uio_cfg(demod, &uio_cfg);
|
||||
if (result) {
|
||||
pr_err("Failed to setup LNA GPIO!\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
uio_data.uio = DRX_UIO1;
|
||||
uio_data.value = state;
|
||||
result = ctrl_uio_write(demod, &uio_data);
|
||||
if (result != 0) {
|
||||
pr_err("Failed to %sable LNA!\n",
|
||||
state ? "en" : "dis");
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Linux DVB Driver for Micronas DRX39xx family (drx3933j)
|
||||
*
|
||||
|
|
@ -12040,7 +12069,6 @@ static int drx39xxj_set_frontend(struct dvb_frontend *fe)
|
|||
enum drx_standard standard = DRX_STANDARD_8VSB;
|
||||
struct drx_channel channel;
|
||||
int result;
|
||||
struct drxuio_data uio_data;
|
||||
static const struct drx_channel def_channel = {
|
||||
/* frequency */ 0,
|
||||
/* bandwidth */ DRX_BANDWIDTH_6MHZ,
|
||||
|
|
@ -12125,13 +12153,7 @@ static int drx39xxj_set_frontend(struct dvb_frontend *fe)
|
|||
return -EINVAL;
|
||||
}
|
||||
/* Just for giggles, let's shut off the LNA again.... */
|
||||
uio_data.uio = DRX_UIO1;
|
||||
uio_data.value = false;
|
||||
result = ctrl_uio_write(demod, &uio_data);
|
||||
if (result != 0) {
|
||||
pr_err("Failed to disable LNA!\n");
|
||||
return 0;
|
||||
}
|
||||
drxj_set_lna_state(demod, false);
|
||||
|
||||
/* After set_frontend, except for strength, stats aren't available */
|
||||
p->strength.stat[0].scale = FE_SCALE_RELATIVE;
|
||||
|
|
@ -12180,21 +12202,28 @@ static int drx39xxj_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
|
|||
|
||||
static int drx39xxj_init(struct dvb_frontend *fe)
|
||||
{
|
||||
/* Bring the demod out of sleep */
|
||||
drx39xxj_set_powerstate(fe, 1);
|
||||
struct drx39xxj_state *state = fe->demodulator_priv;
|
||||
struct drx_demod_instance *demod = state->demod;
|
||||
int rc = 0;
|
||||
|
||||
return 0;
|
||||
if (fe->exit == DVB_FE_DEVICE_RESUME) {
|
||||
/* so drxj_open() does what it needs to do */
|
||||
demod->my_common_attr->is_opened = false;
|
||||
rc = drxj_open(demod);
|
||||
if (rc != 0)
|
||||
pr_err("drx39xxj_init(): DRX open failed rc=%d!\n", rc);
|
||||
} else
|
||||
drx39xxj_set_powerstate(fe, 1);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int drx39xxj_set_lna(struct dvb_frontend *fe)
|
||||
{
|
||||
int result;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct drx39xxj_state *state = fe->demodulator_priv;
|
||||
struct drx_demod_instance *demod = state->demod;
|
||||
struct drxj_data *ext_attr = demod->my_ext_attr;
|
||||
struct drxuio_cfg uio_cfg;
|
||||
struct drxuio_data uio_data;
|
||||
|
||||
if (c->lna) {
|
||||
if (!ext_attr->has_lna) {
|
||||
|
|
@ -12204,26 +12233,7 @@ static int drx39xxj_set_lna(struct dvb_frontend *fe)
|
|||
}
|
||||
}
|
||||
|
||||
/* Turn off the LNA */
|
||||
uio_cfg.uio = DRX_UIO1;
|
||||
uio_cfg.mode = DRX_UIO_MODE_READWRITE;
|
||||
/* Configure user-I/O #3: enable read/write */
|
||||
result = ctrl_set_uio_cfg(demod, &uio_cfg);
|
||||
if (result) {
|
||||
pr_err("Failed to setup LNA GPIO!\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
uio_data.uio = DRX_UIO1;
|
||||
uio_data.value = c->lna;
|
||||
result = ctrl_uio_write(demod, &uio_data);
|
||||
if (result != 0) {
|
||||
pr_err("Failed to %sable LNA!\n",
|
||||
c->lna ? "en" : "dis");
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return drxj_set_lna_state(demod, c->lna);
|
||||
}
|
||||
|
||||
static int drx39xxj_get_tune_settings(struct dvb_frontend *fe,
|
||||
|
|
@ -12238,7 +12248,9 @@ static void drx39xxj_release(struct dvb_frontend *fe)
|
|||
struct drx39xxj_state *state = fe->demodulator_priv;
|
||||
struct drx_demod_instance *demod = state->demod;
|
||||
|
||||
drxj_close(demod);
|
||||
/* if device is removed don't access it */
|
||||
if (fe->exit != DVB_FE_DEVICE_REMOVED)
|
||||
drxj_close(demod);
|
||||
|
||||
kfree(demod->my_ext_attr);
|
||||
kfree(demod->my_common_attr);
|
||||
|
|
@ -12259,8 +12271,6 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
|
|||
struct drxj_data *demod_ext_attr = NULL;
|
||||
struct drx_demod_instance *demod = NULL;
|
||||
struct dtv_frontend_properties *p;
|
||||
struct drxuio_cfg uio_cfg;
|
||||
struct drxuio_data uio_data;
|
||||
int result;
|
||||
|
||||
/* allocate memory for the internal state */
|
||||
|
|
@ -12272,22 +12282,20 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
|
|||
if (demod == NULL)
|
||||
goto error;
|
||||
|
||||
demod_addr = kmalloc(sizeof(struct i2c_device_addr), GFP_KERNEL);
|
||||
demod_addr = kmemdup(&drxj_default_addr_g,
|
||||
sizeof(struct i2c_device_addr), GFP_KERNEL);
|
||||
if (demod_addr == NULL)
|
||||
goto error;
|
||||
memcpy(demod_addr, &drxj_default_addr_g,
|
||||
sizeof(struct i2c_device_addr));
|
||||
|
||||
demod_comm_attr = kmalloc(sizeof(struct drx_common_attr), GFP_KERNEL);
|
||||
demod_comm_attr = kmemdup(&drxj_default_comm_attr_g,
|
||||
sizeof(struct drx_common_attr), GFP_KERNEL);
|
||||
if (demod_comm_attr == NULL)
|
||||
goto error;
|
||||
memcpy(demod_comm_attr, &drxj_default_comm_attr_g,
|
||||
sizeof(struct drx_common_attr));
|
||||
|
||||
demod_ext_attr = kmalloc(sizeof(struct drxj_data), GFP_KERNEL);
|
||||
demod_ext_attr = kmemdup(&drxj_data_g, sizeof(struct drxj_data),
|
||||
GFP_KERNEL);
|
||||
if (demod_ext_attr == NULL)
|
||||
goto error;
|
||||
memcpy(demod_ext_attr, &drxj_data_g, sizeof(struct drxj_data));
|
||||
|
||||
/* setup the state */
|
||||
state->i2c = i2c;
|
||||
|
|
@ -12313,24 +12321,6 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* Turn off the LNA */
|
||||
uio_cfg.uio = DRX_UIO1;
|
||||
uio_cfg.mode = DRX_UIO_MODE_READWRITE;
|
||||
/* Configure user-I/O #3: enable read/write */
|
||||
result = ctrl_set_uio_cfg(demod, &uio_cfg);
|
||||
if (result) {
|
||||
pr_err("Failed to setup LNA GPIO!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
uio_data.uio = DRX_UIO1;
|
||||
uio_data.value = false;
|
||||
result = ctrl_uio_write(demod, &uio_data);
|
||||
if (result != 0) {
|
||||
pr_err("Failed to disable LNA!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &drx39xxj_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
|
|
|
|||
|
|
@ -69,5 +69,4 @@ struct dvb_frontend *drxd_attach(const struct drxd_config *config,
|
|||
}
|
||||
#endif
|
||||
|
||||
extern int drxd_config_i2c(struct dvb_frontend *, int);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2840,7 +2840,7 @@ static int drxd_init(struct dvb_frontend *fe)
|
|||
return err;
|
||||
}
|
||||
|
||||
int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
|
||||
static int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
struct drxd_state *state = fe->demodulator_priv;
|
||||
|
||||
|
|
@ -2849,7 +2849,6 @@ int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
|
|||
|
||||
return DRX_ConfigureI2CBridge(state, onoff);
|
||||
}
|
||||
EXPORT_SYMBOL(drxd_config_i2c);
|
||||
|
||||
static int drxd_get_tune_settings(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *sets)
|
||||
|
|
|
|||
|
|
@ -879,7 +879,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr)
|
|||
/* SNR(X) dB = 10 * ln(X) / ln(10) dB */
|
||||
tmp = DIV_ROUND_CLOSEST(tmp, 8 * M88DS3103_SNR_ITERATIONS);
|
||||
if (tmp)
|
||||
*snr = 100ul * intlog2(tmp) / intlog2(10);
|
||||
*snr = div_u64((u64) 100 * intlog2(tmp), intlog2(10));
|
||||
else
|
||||
*snr = 0;
|
||||
break;
|
||||
|
|
@ -908,7 +908,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr)
|
|||
/* SNR(X) dB = 10 * log10(X) dB */
|
||||
if (signal > noise) {
|
||||
tmp = signal / noise;
|
||||
*snr = 100ul * intlog10(tmp) / (1 << 24);
|
||||
*snr = div_u64((u64) 100 * intlog10(tmp), (1 << 24));
|
||||
} else {
|
||||
*snr = 0;
|
||||
}
|
||||
|
|
@ -926,6 +926,86 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct m88ds3103_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret;
|
||||
unsigned int utmp;
|
||||
u8 buf[3], u8tmp;
|
||||
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
|
||||
|
||||
switch (c->delivery_system) {
|
||||
case SYS_DVBS:
|
||||
ret = m88ds3103_wr_reg(priv, 0xf9, 0x04);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = m88ds3103_rd_reg(priv, 0xf8, &u8tmp);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (!(u8tmp & 0x10)) {
|
||||
u8tmp |= 0x10;
|
||||
|
||||
ret = m88ds3103_rd_regs(priv, 0xf6, buf, 2);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
priv->ber = (buf[1] << 8) | (buf[0] << 0);
|
||||
|
||||
/* restart counters */
|
||||
ret = m88ds3103_wr_reg(priv, 0xf8, u8tmp);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case SYS_DVBS2:
|
||||
ret = m88ds3103_rd_regs(priv, 0xd5, buf, 3);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
utmp = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
|
||||
|
||||
if (utmp > 3000) {
|
||||
ret = m88ds3103_rd_regs(priv, 0xf7, buf, 2);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
priv->ber = (buf[1] << 8) | (buf[0] << 0);
|
||||
|
||||
/* restart counters */
|
||||
ret = m88ds3103_wr_reg(priv, 0xd1, 0x01);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = m88ds3103_wr_reg(priv, 0xf9, 0x01);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = m88ds3103_wr_reg(priv, 0xf9, 0x00);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = m88ds3103_wr_reg(priv, 0xd1, 0x00);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
*ber = priv->ber;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m88ds3103_set_tone(struct dvb_frontend *fe,
|
||||
fe_sec_tone_mode_t fe_sec_tone_mode)
|
||||
|
|
@ -1284,6 +1364,7 @@ static struct dvb_frontend_ops m88ds3103_ops = {
|
|||
|
||||
.read_status = m88ds3103_read_status,
|
||||
.read_snr = m88ds3103_read_snr,
|
||||
.read_ber = m88ds3103_read_ber,
|
||||
|
||||
.diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd,
|
||||
.diseqc_send_burst = m88ds3103_diseqc_send_burst,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "dvb_math.h"
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/math64.h>
|
||||
|
||||
#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw"
|
||||
#define M88DS3103_MCLK_KHZ 96000
|
||||
|
|
@ -34,6 +35,7 @@ struct m88ds3103_priv {
|
|||
struct dvb_frontend fe;
|
||||
fe_delivery_system_t delivery_system;
|
||||
fe_status_t fe_status;
|
||||
u32 ber;
|
||||
bool warm; /* FW running */
|
||||
struct i2c_adapter *i2c_adapter;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -459,6 +459,9 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
|
|||
unsigned layer)
|
||||
{
|
||||
int rc;
|
||||
int interleaving[] = {
|
||||
0, 1, 2, 4, 8
|
||||
};
|
||||
|
||||
static unsigned char reg[] = {
|
||||
[0] = 0x88, /* Layer A */
|
||||
|
|
@ -475,20 +478,7 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
switch ((rc >> 4) & 0x07) {
|
||||
case 1:
|
||||
return GUARD_INTERVAL_1_4;
|
||||
case 2:
|
||||
return GUARD_INTERVAL_1_8;
|
||||
case 3:
|
||||
return GUARD_INTERVAL_1_16;
|
||||
case 4:
|
||||
return GUARD_INTERVAL_1_32;
|
||||
|
||||
default:
|
||||
case 0:
|
||||
return GUARD_INTERVAL_AUTO;
|
||||
}
|
||||
return interleaving[(rc >> 4) & 0x07];
|
||||
}
|
||||
|
||||
static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
|
||||
|
|
@ -566,7 +556,7 @@ static u32 isdbt_rate[3][5][4] = {
|
|||
|
||||
static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
|
||||
u32 modulation, u32 forward_error_correction,
|
||||
u32 interleaving,
|
||||
u32 guard_interval,
|
||||
u32 segment)
|
||||
{
|
||||
struct mb86a20s_state *state = fe->demodulator_priv;
|
||||
|
|
@ -574,7 +564,7 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
|
|||
int mod, fec, guard;
|
||||
|
||||
/*
|
||||
* If modulation/fec/interleaving is not detected, the default is
|
||||
* If modulation/fec/guard is not detected, the default is
|
||||
* to consider the lowest bit rate, to avoid taking too long time
|
||||
* to get BER.
|
||||
*/
|
||||
|
|
@ -612,7 +602,7 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
|
|||
break;
|
||||
}
|
||||
|
||||
switch (interleaving) {
|
||||
switch (guard_interval) {
|
||||
default:
|
||||
case GUARD_INTERVAL_1_4:
|
||||
guard = 0;
|
||||
|
|
@ -703,7 +693,7 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
|
|||
c->layer[layer].interleaving = rc;
|
||||
mb86a20s_layer_bitrate(fe, layer, c->layer[layer].modulation,
|
||||
c->layer[layer].fec,
|
||||
c->layer[layer].interleaving,
|
||||
c->guard_interval,
|
||||
c->layer[layer].segment_count);
|
||||
}
|
||||
|
||||
|
|
@ -721,11 +711,10 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
|
|||
rc = mb86a20s_readreg(state, 0x07);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
c->transmission_mode = TRANSMISSION_MODE_AUTO;
|
||||
if ((rc & 0x60) == 0x20) {
|
||||
switch (rc & 0x0c >> 2) {
|
||||
case 0:
|
||||
c->transmission_mode = TRANSMISSION_MODE_2K;
|
||||
break;
|
||||
/* Only modes 2 and 3 are supported */
|
||||
switch ((rc >> 2) & 0x03) {
|
||||
case 1:
|
||||
c->transmission_mode = TRANSMISSION_MODE_4K;
|
||||
break;
|
||||
|
|
@ -734,7 +723,9 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
|
|||
break;
|
||||
}
|
||||
}
|
||||
c->guard_interval = GUARD_INTERVAL_AUTO;
|
||||
if (!(rc & 0x10)) {
|
||||
/* Guard interval 1/32 is not supported */
|
||||
switch (rc & 0x3) {
|
||||
case 0:
|
||||
c->guard_interval = GUARD_INTERVAL_1_4;
|
||||
|
|
|
|||
1551
drivers/media/dvb-frontends/rtl2832_sdr.c
Normal file
1551
drivers/media/dvb-frontends/rtl2832_sdr.c
Normal file
File diff suppressed because it is too large
Load diff
54
drivers/media/dvb-frontends/rtl2832_sdr.h
Normal file
54
drivers/media/dvb-frontends/rtl2832_sdr.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Realtek RTL2832U SDR driver
|
||||
*
|
||||
* Copyright (C) 2013 Antti Palosaari <crope@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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* GNU Radio plugin "gr-kernel" for device usage will be on:
|
||||
* http://git.linuxtv.org/anttip/gr-kernel.git
|
||||
*
|
||||
* TODO:
|
||||
* Help is very highly welcome for these + all the others you could imagine:
|
||||
* - move controls to V4L2 API
|
||||
* - use libv4l2 for stream format conversions
|
||||
* - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu)
|
||||
* - SDRSharp support
|
||||
*/
|
||||
|
||||
#ifndef RTL2832_SDR_H
|
||||
#define RTL2832_SDR_H
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
|
||||
/* for config struct */
|
||||
#include "rtl2832.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
|
||||
extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
|
||||
struct v4l2_subdev *sd);
|
||||
#else
|
||||
static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
|
||||
struct v4l2_subdev *sd)
|
||||
{
|
||||
dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RTL2832_SDR_H */
|
||||
1040
drivers/media/dvb-frontends/si2165.c
Normal file
1040
drivers/media/dvb-frontends/si2165.c
Normal file
File diff suppressed because it is too large
Load diff
62
drivers/media/dvb-frontends/si2165.h
Normal file
62
drivers/media/dvb-frontends/si2165.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
|
||||
|
||||
Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org>
|
||||
|
||||
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.
|
||||
|
||||
References:
|
||||
http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf
|
||||
*/
|
||||
|
||||
#ifndef _DVB_SI2165_H
|
||||
#define _DVB_SI2165_H
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
enum {
|
||||
SI2165_MODE_OFF = 0x00,
|
||||
SI2165_MODE_PLL_EXT = 0x20,
|
||||
SI2165_MODE_PLL_XTAL = 0x21
|
||||
};
|
||||
|
||||
struct si2165_config {
|
||||
/* i2c addr
|
||||
* possible values: 0x64,0x65,0x66,0x67 */
|
||||
u8 i2c_addr;
|
||||
|
||||
/* external clock or XTAL */
|
||||
u8 chip_mode;
|
||||
|
||||
/* frequency of external clock or xtal in Hz
|
||||
* possible values: 4000000, 16000000, 20000000, 240000000, 27000000
|
||||
*/
|
||||
u32 ref_freq_Hz;
|
||||
|
||||
/* invert the spectrum */
|
||||
bool inversion;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_SI2165)
|
||||
struct dvb_frontend *si2165_attach(
|
||||
const struct si2165_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend *si2165_attach(
|
||||
const struct si2165_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
pr_warn("%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_DVB_SI2165 */
|
||||
|
||||
#endif /* _DVB_SI2165_H */
|
||||
23
drivers/media/dvb-frontends/si2165_priv.h
Normal file
23
drivers/media/dvb-frontends/si2165_priv.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
|
||||
|
||||
Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org>
|
||||
|
||||
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 _DVB_SI2165_PRIV
|
||||
#define _DVB_SI2165_PRIV
|
||||
|
||||
#define SI2165_FIRMWARE "dvb-demod-si2165.fw"
|
||||
|
||||
#endif /* _DVB_SI2165_PRIV */
|
||||
|
|
@ -95,20 +95,17 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
|
||||
switch (c->delivery_system) {
|
||||
case SYS_DVBT:
|
||||
cmd.args[0] = 0xa0;
|
||||
cmd.args[1] = 0x01;
|
||||
memcpy(cmd.args, "\xa0\x01", 2);
|
||||
cmd.wlen = 2;
|
||||
cmd.rlen = 13;
|
||||
break;
|
||||
case SYS_DVBC_ANNEX_A:
|
||||
cmd.args[0] = 0x90;
|
||||
cmd.args[1] = 0x01;
|
||||
memcpy(cmd.args, "\x90\x01", 2);
|
||||
cmd.wlen = 2;
|
||||
cmd.rlen = 9;
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
cmd.args[0] = 0x50;
|
||||
cmd.args[1] = 0x01;
|
||||
memcpy(cmd.args, "\x50\x01", 2);
|
||||
cmd.wlen = 2;
|
||||
cmd.rlen = 14;
|
||||
break;
|
||||
|
|
@ -144,6 +141,15 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
|
||||
s->fe_status = *status;
|
||||
|
||||
if (*status & FE_HAS_LOCK) {
|
||||
c->cnr.len = 1;
|
||||
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4;
|
||||
} else {
|
||||
c->cnr.len = 1;
|
||||
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);
|
||||
|
||||
|
|
@ -243,51 +249,23 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x01\x04\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x03\x10\x17\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x02\x10\x15\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x0b\x10\x88\x13", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
|
@ -295,124 +273,66 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
|||
memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6);
|
||||
cmd.args[4] = delivery_system | bandwidth;
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x04\x10\x15\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x05\x10\xa1\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
/* set DVB-C symbol rate */
|
||||
if (c->delivery_system == SYS_DVBC_ANNEX_A) {
|
||||
memcpy(cmd.args, "\x14\x00\x02\x11", 4);
|
||||
cmd.args[4] = (c->symbol_rate / 1000) & 0xff;
|
||||
cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x0d\x10\xd0\x02", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
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 = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x04\x03\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x03\x03\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x08\x03\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x07\x03\x01\x02", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x06\x03\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x05\x03\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x40", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
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;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 1;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
cmd.args[0] = 0x85;
|
||||
memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
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);
|
||||
|
|
@ -432,59 +352,61 @@ static int si2168_init(struct dvb_frontend *fe)
|
|||
struct si2168 *s = fe->demodulator_priv;
|
||||
int ret, len, remaining;
|
||||
const struct firmware *fw = NULL;
|
||||
u8 *fw_file = SI2168_FIRMWARE;
|
||||
u8 *fw_file;
|
||||
const unsigned int i2c_wr_max = 8;
|
||||
struct si2168_cmd cmd;
|
||||
unsigned int chip_id;
|
||||
|
||||
dev_dbg(&s->client->dev, "%s:\n", __func__);
|
||||
|
||||
cmd.args[0] = 0x13;
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 0;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
cmd.args[0] = 0xc0;
|
||||
cmd.args[1] = 0x12;
|
||||
cmd.args[2] = 0x00;
|
||||
cmd.args[3] = 0x0c;
|
||||
cmd.args[4] = 0x00;
|
||||
cmd.args[5] = 0x0d;
|
||||
cmd.args[6] = 0x16;
|
||||
cmd.args[7] = 0x00;
|
||||
cmd.args[8] = 0x00;
|
||||
cmd.args[9] = 0x00;
|
||||
cmd.args[10] = 0x00;
|
||||
cmd.args[11] = 0x00;
|
||||
cmd.args[12] = 0x00;
|
||||
memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
|
||||
cmd.wlen = 13;
|
||||
cmd.rlen = 0;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
cmd.args[0] = 0xc0;
|
||||
cmd.args[1] = 0x06;
|
||||
cmd.args[2] = 0x01;
|
||||
cmd.args[3] = 0x0f;
|
||||
cmd.args[4] = 0x00;
|
||||
cmd.args[5] = 0x20;
|
||||
cmd.args[6] = 0x20;
|
||||
cmd.args[7] = 0x01;
|
||||
memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
|
||||
cmd.wlen = 8;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
cmd.args[0] = 0x02;
|
||||
/* query chip revision */
|
||||
memcpy(cmd.args, "\x02", 1);
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 13;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
|
||||
cmd.args[4] << 0;
|
||||
|
||||
#define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0)
|
||||
#define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0)
|
||||
#define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0)
|
||||
|
||||
switch (chip_id) {
|
||||
case SI2168_A20:
|
||||
fw_file = SI2168_A20_FIRMWARE;
|
||||
break;
|
||||
case SI2168_A30:
|
||||
fw_file = SI2168_A30_FIRMWARE;
|
||||
break;
|
||||
case SI2168_B40:
|
||||
fw_file = SI2168_B40_FIRMWARE;
|
||||
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],
|
||||
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);
|
||||
|
|
@ -492,9 +414,22 @@ static int si2168_init(struct dvb_frontend *fe)
|
|||
/* request the firmware, this will block and timeout */
|
||||
ret = request_firmware(&fw, fw_file, &s->client->dev);
|
||||
if (ret) {
|
||||
dev_err(&s->client->dev, "%s: firmare file '%s' not found\n",
|
||||
KBUILD_MODNAME, fw_file);
|
||||
goto err;
|
||||
/* fallback mechanism to handle old name for Si2168 B40 fw */
|
||||
if (chip_id == SI2168_B40) {
|
||||
fw_file = SI2168_B40_FIRMWARE_FALLBACK;
|
||||
ret = request_firmware(&fw, fw_file, &s->client->dev);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
dev_notice(&s->client->dev,
|
||||
"%s: please install firmware file '%s'\n",
|
||||
KBUILD_MODNAME, SI2168_B40_FIRMWARE);
|
||||
} else {
|
||||
dev_err(&s->client->dev,
|
||||
"%s: firmware file '%s' not found\n",
|
||||
KBUILD_MODNAME, fw_file);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
|
||||
|
|
@ -520,8 +455,7 @@ static int si2168_init(struct dvb_frontend *fe)
|
|||
release_firmware(fw);
|
||||
fw = NULL;
|
||||
|
||||
cmd.args[0] = 0x01;
|
||||
cmd.args[1] = 0x01;
|
||||
memcpy(cmd.args, "\x01\x01", 2);
|
||||
cmd.wlen = 2;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
|
|
@ -545,12 +479,24 @@ err:
|
|||
static int si2168_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct si2168 *s = fe->demodulator_priv;
|
||||
int ret;
|
||||
struct si2168_cmd cmd;
|
||||
|
||||
dev_dbg(&s->client->dev, "%s:\n", __func__);
|
||||
|
||||
s->active = false;
|
||||
|
||||
memcpy(cmd.args, "\x13", 1);
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 0;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int si2168_get_tune_settings(struct dvb_frontend *fe,
|
||||
|
|
@ -660,7 +606,6 @@ static int si2168_probe(struct i2c_client *client,
|
|||
struct si2168_config *config = client->dev.platform_data;
|
||||
struct si2168 *s;
|
||||
int ret;
|
||||
struct si2168_cmd cmd;
|
||||
|
||||
dev_dbg(&client->dev, "%s:\n", __func__);
|
||||
|
||||
|
|
@ -674,18 +619,13 @@ static int si2168_probe(struct i2c_client *client,
|
|||
s->client = client;
|
||||
mutex_init(&s->i2c_mutex);
|
||||
|
||||
/* check if the demod is there */
|
||||
cmd.wlen = 0;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* create mux i2c adapter for tuner */
|
||||
s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
|
||||
0, 0, 0, si2168_select, si2168_deselect);
|
||||
if (s->adapter == NULL)
|
||||
if (s->adapter == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
|
||||
|
|
@ -743,4 +683,6 @@ module_i2c_driver(si2168_driver);
|
|||
MODULE_AUTHOR("Antti Palosaari <[email protected]>");
|
||||
MODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE(SI2168_FIRMWARE);
|
||||
MODULE_FIRMWARE(SI2168_A20_FIRMWARE);
|
||||
MODULE_FIRMWARE(SI2168_A30_FIRMWARE);
|
||||
MODULE_FIRMWARE(SI2168_B40_FIRMWARE);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,10 @@
|
|||
#include <linux/firmware.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
|
||||
#define SI2168_FIRMWARE "dvb-demod-si2168-02.fw"
|
||||
#define SI2168_A20_FIRMWARE "dvb-demod-si2168-a20-01.fw"
|
||||
#define SI2168_A30_FIRMWARE "dvb-demod-si2168-a30-01.fw"
|
||||
#define SI2168_B40_FIRMWARE "dvb-demod-si2168-b40-01.fw"
|
||||
#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
|
||||
|
||||
/* state struct */
|
||||
struct si2168 {
|
||||
|
|
@ -36,9 +39,9 @@ struct si2168 {
|
|||
};
|
||||
|
||||
/* firmare command struct */
|
||||
#define SI2157_ARGLEN 30
|
||||
#define SI2168_ARGLEN 30
|
||||
struct si2168_cmd {
|
||||
u8 args[SI2157_ARGLEN];
|
||||
u8 args[SI2168_ARGLEN];
|
||||
unsigned wlen;
|
||||
unsigned rlen;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,17 +21,14 @@
|
|||
|
||||
static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state t_state;
|
||||
int err = 0;
|
||||
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
if (tuner_ops->get_state) {
|
||||
if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
|
||||
err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
|
||||
if (err < 0) {
|
||||
printk("%s: Invalid parameter\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -42,18 +39,16 @@ static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
|||
|
||||
static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state t_state;
|
||||
int err = 0;
|
||||
|
||||
t_state.frequency = frequency;
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
|
||||
if (tuner_ops->set_state) {
|
||||
if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
|
||||
err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
|
||||
if (err < 0) {
|
||||
printk("%s: Invalid parameter\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -68,12 +63,9 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
|||
struct tuner_state t_state;
|
||||
int err = 0;
|
||||
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
if (tuner_ops->get_state) {
|
||||
if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
|
||||
err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
|
||||
if (err < 0) {
|
||||
printk("%s: Invalid parameter\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -84,18 +76,16 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
|||
|
||||
static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state t_state;
|
||||
int err = 0;
|
||||
|
||||
t_state.bandwidth = bandwidth;
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
|
||||
if (tuner_ops->set_state) {
|
||||
if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
|
||||
err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
|
||||
if (err < 0) {
|
||||
printk("%s: Invalid parameter\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,11 @@
|
|||
|
||||
static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state state;
|
||||
int err = 0;
|
||||
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
if (tuner_ops->get_state) {
|
||||
if (frontend_ops->i2c_gate_ctrl)
|
||||
frontend_ops->i2c_gate_ctrl(fe, 1);
|
||||
|
|
@ -49,16 +45,13 @@ static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
|
|||
|
||||
static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state state;
|
||||
int err = 0;
|
||||
|
||||
state.frequency = frequency;
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
|
||||
if (tuner_ops->set_state) {
|
||||
if (frontend_ops->i2c_gate_ctrl)
|
||||
frontend_ops->i2c_gate_ctrl(fe, 1);
|
||||
|
|
@ -79,15 +72,11 @@ static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
|
|||
|
||||
static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state state;
|
||||
int err = 0;
|
||||
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
if (tuner_ops->get_state) {
|
||||
if (frontend_ops->i2c_gate_ctrl)
|
||||
frontend_ops->i2c_gate_ctrl(fe, 1);
|
||||
|
|
@ -109,16 +98,13 @@ static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
|
|||
|
||||
static int stb6100_set_bandw(struct dvb_frontend *fe, u32 bandwidth)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state state;
|
||||
int err = 0;
|
||||
|
||||
state.bandwidth = bandwidth;
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
|
||||
if (tuner_ops->set_state) {
|
||||
if (frontend_ops->i2c_gate_ctrl)
|
||||
frontend_ops->i2c_gate_ctrl(fe, 1);
|
||||
|
|
|
|||
|
|
@ -922,18 +922,13 @@ static int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable)
|
|||
|
||||
static u32 stv0367_get_tuner_freq(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
u32 freq = 0;
|
||||
int err = 0;
|
||||
|
||||
dprintk("%s:\n", __func__);
|
||||
|
||||
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
if (tuner_ops->get_frequency) {
|
||||
err = tuner_ops->get_frequency(fe, &freq);
|
||||
if (err < 0) {
|
||||
|
|
|
|||
|
|
@ -1030,7 +1030,7 @@ static int ChannelConfiguration(struct tda_state *state,
|
|||
state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
|
||||
|
||||
if ((Standard == HF_FM_Radio) && state->m_bFMInput)
|
||||
state->m_Regs[EP4] |= 80;
|
||||
state->m_Regs[EP4] |= 0x80;
|
||||
|
||||
state->m_Regs[MPD] &= ~0x80;
|
||||
if (Standard > HF_AnalogMax)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ enum HF_S {
|
|||
HF_DVBC_8MHZ, HF_DVBC
|
||||
};
|
||||
|
||||
struct SStandardParam m_StandardTable[] = {
|
||||
static struct SStandardParam m_StandardTable[] = {
|
||||
{ 0, 0, 0x00, 0x00 }, /* HF_None */
|
||||
{ 6000000, 7000000, 0x1D, 0x2C }, /* HF_B, */
|
||||
{ 6900000, 8000000, 0x1E, 0x2C }, /* HF_DK, */
|
||||
|
|
@ -27,7 +27,7 @@ struct SStandardParam m_StandardTable[] = {
|
|||
{ 0, 0, 0x00, 0x00 }, /* HF_DVBC (Unused) */
|
||||
};
|
||||
|
||||
struct SMap m_BP_Filter_Map[] = {
|
||||
static struct SMap m_BP_Filter_Map[] = {
|
||||
{ 62000000, 0x00 },
|
||||
{ 84000000, 0x01 },
|
||||
{ 100000000, 0x02 },
|
||||
|
|
@ -799,14 +799,14 @@ static struct SRFBandMap m_RF_Band_Map[7] = {
|
|||
{ 865000000, 489500000, 697500000, 842000000},
|
||||
};
|
||||
|
||||
u8 m_Thermometer_Map_1[16] = {
|
||||
static u8 m_Thermometer_Map_1[16] = {
|
||||
60, 62, 66, 64,
|
||||
74, 72, 68, 70,
|
||||
90, 88, 84, 86,
|
||||
76, 78, 82, 80,
|
||||
};
|
||||
|
||||
u8 m_Thermometer_Map_2[16] = {
|
||||
static u8 m_Thermometer_Map_2[16] = {
|
||||
92, 94, 98, 96,
|
||||
106, 104, 100, 102,
|
||||
122, 120, 116, 118,
|
||||
|
|
|
|||
|
|
@ -19,17 +19,14 @@
|
|||
|
||||
static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state t_state;
|
||||
int err = 0;
|
||||
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
if (tuner_ops->get_state) {
|
||||
if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
|
||||
err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
|
||||
if (err < 0) {
|
||||
printk("%s: Invalid parameter\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -41,18 +38,16 @@ static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
|||
|
||||
static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency)
|
||||
{
|
||||
struct dvb_frontend_ops *frontend_ops = NULL;
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
struct dvb_frontend_ops *frontend_ops = &fe->ops;
|
||||
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
|
||||
struct tuner_state t_state;
|
||||
int err = 0;
|
||||
|
||||
t_state.frequency = frequency;
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
|
||||
if (tuner_ops->set_state) {
|
||||
if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
|
||||
err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
|
||||
if (err < 0) {
|
||||
printk("%s: Invalid parameter\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -68,12 +63,9 @@ static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
|||
struct tuner_state t_state;
|
||||
int err = 0;
|
||||
|
||||
if (&fe->ops)
|
||||
frontend_ops = &fe->ops;
|
||||
if (&frontend_ops->tuner_ops)
|
||||
tuner_ops = &frontend_ops->tuner_ops;
|
||||
if (tuner_ops->get_state) {
|
||||
if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
|
||||
err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
|
||||
if (err < 0) {
|
||||
printk("%s: Invalid parameter\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -551,6 +551,7 @@ config VIDEO_MT9V032
|
|||
tristate "Micron MT9V032 sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
select REGMAP_I2C
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the Micron
|
||||
MT9V032 752x480 CMOS sensor.
|
||||
|
|
|
|||
|
|
@ -663,7 +663,6 @@ static int adv7180_remove(struct i2c_client *client)
|
|||
if (state->irq > 0)
|
||||
free_irq(client->irq, state);
|
||||
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
adv7180_exit_controls(state);
|
||||
mutex_destroy(&state->mutex);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -2588,8 +2588,11 @@ static const struct adv7604_reg_seq adv7604_recommended_settings_hdmi[] = {
|
|||
};
|
||||
|
||||
static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = {
|
||||
/* ADV7611 Register Settings Recommendations Rev 1.5, May 2014 */
|
||||
{ ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 },
|
||||
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x0c },
|
||||
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x9b), 0x03 },
|
||||
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x08 },
|
||||
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x85), 0x1f },
|
||||
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 },
|
||||
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda },
|
||||
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 },
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ module_param(debug, int, 0644); /* debug level (0,1,2) */
|
|||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
|
||||
int size, int offset)
|
||||
static int get_key_haup_common(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *ptoggle, int size, int offset)
|
||||
{
|
||||
unsigned char buf[6];
|
||||
int start, range, toggle, dev, code, ircode;
|
||||
|
|
@ -86,19 +86,10 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
|
|||
if (!start)
|
||||
/* no key pressed */
|
||||
return 0;
|
||||
/*
|
||||
* Hauppauge remotes (black/silver) always use
|
||||
* specific device ids. If we do not filter the
|
||||
* device ids then messages destined for devices
|
||||
* such as TVs (id=0) will get through causing
|
||||
* mis-fired events.
|
||||
*
|
||||
* We also filter out invalid key presses which
|
||||
* produce annoying debug log entries.
|
||||
*/
|
||||
ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
|
||||
if ((ircode & 0x1fff)==0x1fff)
|
||||
/* invalid key press */
|
||||
|
||||
/* filter out invalid key presses */
|
||||
ircode = (start << 12) | (toggle << 11) | (dev << 6) | code;
|
||||
if ((ircode & 0x1fff) == 0x1fff)
|
||||
return 0;
|
||||
|
||||
if (!range)
|
||||
|
|
@ -107,18 +98,20 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
|
|||
dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
|
||||
start, range, toggle, dev, code);
|
||||
|
||||
/* return key */
|
||||
*ir_key = (dev << 8) | code;
|
||||
*ir_raw = ircode;
|
||||
*protocol = RC_TYPE_RC5;
|
||||
*scancode = RC_SCANCODE_RC5(dev, code);
|
||||
*ptoggle = toggle;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_haup(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
|
||||
return get_key_haup_common (ir, protocol, scancode, toggle, 3, 0);
|
||||
}
|
||||
|
||||
static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1] = { 0 };
|
||||
|
|
@ -133,10 +126,11 @@ static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
if (ret != 1)
|
||||
return (ret < 0) ? ret : -EINVAL;
|
||||
|
||||
return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
|
||||
return get_key_haup_common(ir, protocol, scancode, toggle, 6, 3);
|
||||
}
|
||||
|
||||
static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_pixelview(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char b;
|
||||
|
||||
|
|
@ -145,12 +139,15 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
dprintk(1,"read error\n");
|
||||
return -EIO;
|
||||
}
|
||||
*ir_key = b;
|
||||
*ir_raw = b;
|
||||
|
||||
*protocol = RC_TYPE_OTHER;
|
||||
*scancode = b;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_fusionhdtv(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char buf[4];
|
||||
|
||||
|
|
@ -168,13 +165,14 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
if(buf[0] != 0x1 || buf[1] != 0xfe)
|
||||
return 0;
|
||||
|
||||
*ir_key = buf[2];
|
||||
*ir_raw = (buf[2] << 8) | buf[3];
|
||||
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = buf[2];
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_knc1(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char b;
|
||||
|
||||
|
|
@ -197,13 +195,14 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
/* keep old data */
|
||||
return 1;
|
||||
|
||||
*ir_key = b;
|
||||
*ir_raw = b;
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = b;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_key_avermedia_cardbus(struct IR_i2c *ir,
|
||||
u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_avermedia_cardbus(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char subaddr, key, keygroup;
|
||||
struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
|
||||
|
|
@ -237,12 +236,11 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
|
|||
}
|
||||
key |= (keygroup & 1) << 6;
|
||||
|
||||
*ir_key = key;
|
||||
*ir_raw = key;
|
||||
if (!strcmp(ir->ir_codes, RC_MAP_AVERMEDIA_M733A_RM_K6)) {
|
||||
*ir_key |= keygroup << 8;
|
||||
*ir_raw |= keygroup << 8;
|
||||
}
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = key;
|
||||
if (ir->c->addr == 0x41) /* AVerMedia EM78P153 */
|
||||
*scancode |= keygroup << 8;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -250,19 +248,22 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
|
|||
|
||||
static int ir_key_poll(struct IR_i2c *ir)
|
||||
{
|
||||
static u32 ir_key, ir_raw;
|
||||
enum rc_type protocol;
|
||||
u32 scancode;
|
||||
u8 toggle;
|
||||
int rc;
|
||||
|
||||
dprintk(3, "%s\n", __func__);
|
||||
rc = ir->get_key(ir, &ir_key, &ir_raw);
|
||||
rc = ir->get_key(ir, &protocol, &scancode, &toggle);
|
||||
if (rc < 0) {
|
||||
dprintk(2,"error\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
|
||||
rc_keydown(ir->rc, ir_key, 0);
|
||||
dprintk(1, "%s: proto = 0x%04x, scancode = 0x%08x\n",
|
||||
__func__, protocol, scancode);
|
||||
rc_keydown(ir->rc, protocol, scancode, toggle);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -327,7 +328,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
case 0x6b:
|
||||
name = "FusionHDTV";
|
||||
ir->get_key = get_key_fusionhdtv;
|
||||
rc_type = RC_BIT_RC5;
|
||||
rc_type = RC_BIT_UNKNOWN;
|
||||
ir_codes = RC_MAP_FUSIONHDTV_MCE;
|
||||
break;
|
||||
case 0x40:
|
||||
|
|
@ -431,8 +432,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
* Initialize the other fields of rc_dev
|
||||
*/
|
||||
rc->map_name = ir->ir_codes;
|
||||
rc_set_allowed_protocols(rc, rc_type);
|
||||
rc_set_enabled_protocols(rc, rc_type);
|
||||
rc->allowed_protocols = rc_type;
|
||||
rc->enabled_protocols = rc_type;
|
||||
if (!rc->driver_name)
|
||||
rc->driver_name = MODULE_NAME;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Driver for MT9V032 CMOS Image Sensor from Micron
|
||||
* Driver for MT9V022, MT9V024, MT9V032, and MT9V034 CMOS Image Sensors
|
||||
*
|
||||
* Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
|
|
@ -87,6 +88,7 @@
|
|||
#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
|
||||
#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
|
||||
#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
|
||||
#define MT9V032_READ_MODE_RESERVED 0x0300
|
||||
#define MT9V032_PIXEL_OPERATION_MODE 0x0f
|
||||
#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
|
||||
#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
|
||||
|
|
@ -133,8 +135,12 @@
|
|||
#define MT9V032_THERMAL_INFO 0xc1
|
||||
|
||||
enum mt9v032_model {
|
||||
MT9V032_MODEL_V032_COLOR,
|
||||
MT9V032_MODEL_V032_MONO,
|
||||
MT9V032_MODEL_V022_COLOR, /* MT9V022IX7ATC */
|
||||
MT9V032_MODEL_V022_MONO, /* MT9V022IX7ATM */
|
||||
MT9V032_MODEL_V024_COLOR, /* MT9V024IA7XTC */
|
||||
MT9V032_MODEL_V024_MONO, /* MT9V024IA7XTM */
|
||||
MT9V032_MODEL_V032_COLOR, /* MT9V032C12STM */
|
||||
MT9V032_MODEL_V032_MONO, /* MT9V032C12STC */
|
||||
MT9V032_MODEL_V034_COLOR,
|
||||
MT9V032_MODEL_V034_MONO,
|
||||
};
|
||||
|
|
@ -160,14 +166,14 @@ struct mt9v032_model_info {
|
|||
};
|
||||
|
||||
static const struct mt9v032_model_version mt9v032_versions[] = {
|
||||
{ MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" },
|
||||
{ MT9V032_CHIP_ID_REV3, "MT9V032 rev3" },
|
||||
{ MT9V034_CHIP_ID_REV1, "MT9V034 rev1" },
|
||||
{ MT9V032_CHIP_ID_REV1, "MT9V022/MT9V032 rev1/2" },
|
||||
{ MT9V032_CHIP_ID_REV3, "MT9V022/MT9V032 rev3" },
|
||||
{ MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" },
|
||||
};
|
||||
|
||||
static const struct mt9v032_model_data mt9v032_model_data[] = {
|
||||
{
|
||||
/* MT9V032 revisions 1/2/3 */
|
||||
/* MT9V022, MT9V032 revisions 1/2/3 */
|
||||
.min_row_time = 660,
|
||||
.min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
|
||||
.min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
|
||||
|
|
@ -176,7 +182,7 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
|
|||
.max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
|
||||
.pclk_reg = MT9V032_PIXEL_CLOCK,
|
||||
}, {
|
||||
/* MT9V034 */
|
||||
/* MT9V024, MT9V034 */
|
||||
.min_row_time = 690,
|
||||
.min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
|
||||
.min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
|
||||
|
|
@ -188,6 +194,22 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
|
|||
};
|
||||
|
||||
static const struct mt9v032_model_info mt9v032_models[] = {
|
||||
[MT9V032_MODEL_V022_COLOR] = {
|
||||
.data = &mt9v032_model_data[0],
|
||||
.color = true,
|
||||
},
|
||||
[MT9V032_MODEL_V022_MONO] = {
|
||||
.data = &mt9v032_model_data[0],
|
||||
.color = false,
|
||||
},
|
||||
[MT9V032_MODEL_V024_COLOR] = {
|
||||
.data = &mt9v032_model_data[1],
|
||||
.color = true,
|
||||
},
|
||||
[MT9V032_MODEL_V024_MONO] = {
|
||||
.data = &mt9v032_model_data[1],
|
||||
.color = false,
|
||||
},
|
||||
[MT9V032_MODEL_V032_COLOR] = {
|
||||
.data = &mt9v032_model_data[0],
|
||||
.color = true,
|
||||
|
|
@ -224,6 +246,7 @@ struct mt9v032 {
|
|||
struct mutex power_lock;
|
||||
int power_count;
|
||||
|
||||
struct regmap *regmap;
|
||||
struct clk *clk;
|
||||
|
||||
struct mt9v032_platform_data *pdata;
|
||||
|
|
@ -231,7 +254,6 @@ struct mt9v032 {
|
|||
const struct mt9v032_model_version *version;
|
||||
|
||||
u32 sysclk;
|
||||
u16 chip_control;
|
||||
u16 aec_agc;
|
||||
u16 hblank;
|
||||
struct {
|
||||
|
|
@ -245,40 +267,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
|
|||
return container_of(sd, struct mt9v032, subdev);
|
||||
}
|
||||
|
||||
static int mt9v032_read(struct i2c_client *client, const u8 reg)
|
||||
{
|
||||
s32 data = i2c_smbus_read_word_swapped(client, reg);
|
||||
dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
|
||||
data, reg);
|
||||
return data;
|
||||
}
|
||||
|
||||
static int mt9v032_write(struct i2c_client *client, const u8 reg,
|
||||
const u16 data)
|
||||
{
|
||||
dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
|
||||
data, reg);
|
||||
return i2c_smbus_write_word_swapped(client, reg, data);
|
||||
}
|
||||
|
||||
static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
u16 value = (mt9v032->chip_control & ~clear) | set;
|
||||
int ret;
|
||||
|
||||
ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mt9v032->chip_control = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
struct regmap *map = mt9v032->regmap;
|
||||
u16 value = mt9v032->aec_agc;
|
||||
int ret;
|
||||
|
||||
|
|
@ -287,7 +279,7 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
|
|||
else
|
||||
value &= ~which;
|
||||
|
||||
ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
|
||||
ret = regmap_write(map, MT9V032_AEC_AGC_ENABLE, value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -298,23 +290,23 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
|
|||
static int
|
||||
mt9v032_update_hblank(struct mt9v032 *mt9v032)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
struct v4l2_rect *crop = &mt9v032->crop;
|
||||
unsigned int min_hblank = mt9v032->model->data->min_hblank;
|
||||
unsigned int hblank;
|
||||
|
||||
if (mt9v032->version->version == MT9V034_CHIP_ID_REV1)
|
||||
min_hblank += (mt9v032->hratio - 1) * 10;
|
||||
min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width,
|
||||
(int)min_hblank);
|
||||
min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width,
|
||||
min_hblank);
|
||||
hblank = max_t(unsigned int, mt9v032->hblank, min_hblank);
|
||||
|
||||
return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank);
|
||||
return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING,
|
||||
hblank);
|
||||
}
|
||||
|
||||
static int mt9v032_power_on(struct mt9v032 *mt9v032)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
struct regmap *map = mt9v032->regmap;
|
||||
int ret;
|
||||
|
||||
ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk);
|
||||
|
|
@ -328,15 +320,15 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
|
|||
udelay(1);
|
||||
|
||||
/* Reset the chip and stop data read out */
|
||||
ret = mt9v032_write(client, MT9V032_RESET, 1);
|
||||
ret = regmap_write(map, MT9V032_RESET, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mt9v032_write(client, MT9V032_RESET, 0);
|
||||
ret = regmap_write(map, MT9V032_RESET, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
|
||||
return regmap_write(map, MT9V032_CHIP_CONTROL, 0);
|
||||
}
|
||||
|
||||
static void mt9v032_power_off(struct mt9v032 *mt9v032)
|
||||
|
|
@ -346,7 +338,7 @@ static void mt9v032_power_off(struct mt9v032 *mt9v032)
|
|||
|
||||
static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
struct regmap *map = mt9v032->regmap;
|
||||
int ret;
|
||||
|
||||
if (!on) {
|
||||
|
|
@ -360,14 +352,14 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
|
|||
|
||||
/* Configure the pixel clock polarity */
|
||||
if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
|
||||
ret = mt9v032_write(client, mt9v032->model->data->pclk_reg,
|
||||
ret = regmap_write(map, mt9v032->model->data->pclk_reg,
|
||||
MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disable the noise correction algorithm and restore the controls. */
|
||||
ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
|
||||
ret = regmap_write(map, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -411,38 +403,39 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
|
|||
const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
|
||||
| MT9V032_CHIP_CONTROL_DOUT_ENABLE
|
||||
| MT9V032_CHIP_CONTROL_SEQUENTIAL;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
||||
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
struct v4l2_rect *crop = &mt9v032->crop;
|
||||
struct regmap *map = mt9v032->regmap;
|
||||
unsigned int hbin;
|
||||
unsigned int vbin;
|
||||
int ret;
|
||||
|
||||
if (!enable)
|
||||
return mt9v032_set_chip_control(mt9v032, mode, 0);
|
||||
return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, 0);
|
||||
|
||||
/* Configure the window size and row/column bin */
|
||||
hbin = fls(mt9v032->hratio) - 1;
|
||||
vbin = fls(mt9v032->vratio) - 1;
|
||||
ret = mt9v032_write(client, MT9V032_READ_MODE,
|
||||
hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
|
||||
vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
|
||||
ret = regmap_update_bits(map, MT9V032_READ_MODE,
|
||||
~MT9V032_READ_MODE_RESERVED,
|
||||
hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
|
||||
vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
|
||||
ret = regmap_write(map, MT9V032_COLUMN_START, crop->left);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
|
||||
ret = regmap_write(map, MT9V032_ROW_START, crop->top);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
|
||||
ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
|
||||
ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -451,7 +444,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
|
|||
return ret;
|
||||
|
||||
/* Switch to master "normal" mode */
|
||||
return mt9v032_set_chip_control(mt9v032, 0, mode);
|
||||
return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, mode);
|
||||
}
|
||||
|
||||
static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
|
||||
|
|
@ -633,7 +626,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
{
|
||||
struct mt9v032 *mt9v032 =
|
||||
container_of(ctrl->handler, struct mt9v032, ctrls);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
struct regmap *map = mt9v032->regmap;
|
||||
u32 freq;
|
||||
u16 data;
|
||||
|
||||
|
|
@ -643,23 +636,23 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
ctrl->val);
|
||||
|
||||
case V4L2_CID_GAIN:
|
||||
return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
|
||||
return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val);
|
||||
|
||||
case V4L2_CID_EXPOSURE_AUTO:
|
||||
return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
|
||||
!ctrl->val);
|
||||
|
||||
case V4L2_CID_EXPOSURE:
|
||||
return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
|
||||
ctrl->val);
|
||||
return regmap_write(map, MT9V032_TOTAL_SHUTTER_WIDTH,
|
||||
ctrl->val);
|
||||
|
||||
case V4L2_CID_HBLANK:
|
||||
mt9v032->hblank = ctrl->val;
|
||||
return mt9v032_update_hblank(mt9v032);
|
||||
|
||||
case V4L2_CID_VBLANK:
|
||||
return mt9v032_write(client, MT9V032_VERTICAL_BLANKING,
|
||||
ctrl->val);
|
||||
return regmap_write(map, MT9V032_VERTICAL_BLANKING,
|
||||
ctrl->val);
|
||||
|
||||
case V4L2_CID_PIXEL_RATE:
|
||||
case V4L2_CID_LINK_FREQ:
|
||||
|
|
@ -667,7 +660,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
break;
|
||||
|
||||
freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
|
||||
mt9v032->pixel_rate->val64 = freq;
|
||||
*mt9v032->pixel_rate->p_new.p_s64 = freq;
|
||||
mt9v032->sysclk = freq;
|
||||
break;
|
||||
|
||||
|
|
@ -696,7 +689,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
| MT9V032_TEST_PATTERN_FLIP;
|
||||
break;
|
||||
}
|
||||
return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
|
||||
return regmap_write(map, MT9V032_TEST_PATTERN, data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -764,7 +757,7 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
|
|||
struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
||||
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
unsigned int i;
|
||||
s32 version;
|
||||
u32 version;
|
||||
int ret;
|
||||
|
||||
dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
|
||||
|
|
@ -777,10 +770,10 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
|
|||
}
|
||||
|
||||
/* Read and check the sensor version */
|
||||
version = mt9v032_read(client, MT9V032_CHIP_VERSION);
|
||||
if (version < 0) {
|
||||
ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Failed reading chip version\n");
|
||||
return version;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) {
|
||||
|
|
@ -867,6 +860,13 @@ static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
|
|||
.close = mt9v032_close,
|
||||
};
|
||||
|
||||
static const struct regmap_config mt9v032_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 16,
|
||||
.max_register = 0xff,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Driver initialization and probing
|
||||
*/
|
||||
|
|
@ -890,6 +890,10 @@ static int mt9v032_probe(struct i2c_client *client,
|
|||
if (!mt9v032)
|
||||
return -ENOMEM;
|
||||
|
||||
mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config);
|
||||
if (IS_ERR(mt9v032->regmap))
|
||||
return PTR_ERR(mt9v032->regmap);
|
||||
|
||||
mt9v032->clk = devm_clk_get(&client->dev, NULL);
|
||||
if (IS_ERR(mt9v032->clk))
|
||||
return PTR_ERR(mt9v032->clk);
|
||||
|
|
@ -931,7 +935,7 @@ static int mt9v032_probe(struct i2c_client *client,
|
|||
|
||||
mt9v032->pixel_rate =
|
||||
v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
|
||||
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
|
||||
|
||||
if (pdata && pdata->link_freqs) {
|
||||
unsigned int def = 0;
|
||||
|
|
@ -984,10 +988,19 @@ static int mt9v032_probe(struct i2c_client *client,
|
|||
|
||||
mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
|
||||
|
||||
if (ret < 0)
|
||||
v4l2_ctrl_handler_free(&mt9v032->ctrls);
|
||||
goto err;
|
||||
|
||||
mt9v032->subdev.dev = &client->dev;
|
||||
ret = v4l2_async_register_subdev(&mt9v032->subdev);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
media_entity_cleanup(&mt9v032->subdev.entity);
|
||||
v4l2_ctrl_handler_free(&mt9v032->ctrls);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -996,6 +1009,7 @@ static int mt9v032_remove(struct i2c_client *client)
|
|||
struct v4l2_subdev *subdev = i2c_get_clientdata(client);
|
||||
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
|
||||
v4l2_async_unregister_subdev(subdev);
|
||||
v4l2_ctrl_handler_free(&mt9v032->ctrls);
|
||||
v4l2_device_unregister_subdev(subdev);
|
||||
media_entity_cleanup(&subdev->entity);
|
||||
|
|
@ -1004,6 +1018,10 @@ static int mt9v032_remove(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id mt9v032_id[] = {
|
||||
{ "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] },
|
||||
{ "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] },
|
||||
{ "mt9v024", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_COLOR] },
|
||||
{ "mt9v024m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_MONO] },
|
||||
{ "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] },
|
||||
{ "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] },
|
||||
{ "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] },
|
||||
|
|
|
|||
|
|
@ -554,6 +554,7 @@ static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
|||
nf = noon010_try_fmt(sd, &fmt->format);
|
||||
noon010_try_frame_size(&fmt->format, &size);
|
||||
fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
|
||||
fmt->format.field = V4L2_FIELD_NONE;
|
||||
|
||||
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
|
||||
if (fh) {
|
||||
|
|
|
|||
|
|
@ -594,6 +594,7 @@ static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
|||
pf = s5k4ecgx_try_fmt(sd, &fmt->format);
|
||||
s5k4ecgx_try_frame_size(&fmt->format, &fsize);
|
||||
fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
|
||||
fmt->format.field = V4L2_FIELD_NONE;
|
||||
|
||||
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
|
||||
if (fh) {
|
||||
|
|
|
|||
|
|
@ -1313,6 +1313,8 @@ static int s5k5baf_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
|||
const struct s5k5baf_pixfmt *pixfmt;
|
||||
int ret = 0;
|
||||
|
||||
mf->field = V4L2_FIELD_NONE;
|
||||
|
||||
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
|
||||
*v4l2_subdev_get_try_format(fh, fmt->pad) = *mf;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
|
|||
|
||||
fmt = find_sensor_format(mf);
|
||||
mf->code = fmt->code;
|
||||
mf->field = V4L2_FIELD_NONE;
|
||||
v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
|
||||
S5K6A3_SENSOR_MAX_WIDTH, 0,
|
||||
&mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
|
||||
|
|
|
|||
|
|
@ -297,8 +297,8 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
|
|||
if (rval < 0)
|
||||
return rval;
|
||||
|
||||
sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
|
||||
sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
|
||||
*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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -533,7 +533,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
|||
|
||||
sensor->pixel_rate_parray = v4l2_ctrl_new_std(
|
||||
&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
|
||||
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
|
||||
|
||||
if (sensor->pixel_array->ctrl_handler.error) {
|
||||
dev_err(&client->dev,
|
||||
|
|
@ -562,7 +562,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
|||
|
||||
sensor->pixel_rate_csi = v4l2_ctrl_new_std(
|
||||
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
|
||||
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
|
||||
|
||||
if (sensor->src->ctrl_handler.error) {
|
||||
dev_err(&client->dev,
|
||||
|
|
@ -1554,6 +1554,7 @@ static int __smiapp_get_format(struct v4l2_subdev *subdev,
|
|||
fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
|
||||
fmt->format.width = r->width;
|
||||
fmt->format.height = r->height;
|
||||
fmt->format.field = V4L2_FIELD_NONE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1687,6 +1688,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
|
|||
fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
|
||||
fmt->format.width &= ~1;
|
||||
fmt->format.height &= ~1;
|
||||
fmt->format.field = V4L2_FIELD_NONE;
|
||||
|
||||
fmt->format.width =
|
||||
clamp(fmt->format.width,
|
||||
|
|
@ -2544,9 +2546,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
|||
}
|
||||
|
||||
snprintf(this->sd.name,
|
||||
sizeof(this->sd.name), "%s %d-%4.4x %s",
|
||||
sensor->minfo.name, i2c_adapter_id(client->adapter),
|
||||
client->addr, _this->name);
|
||||
sizeof(this->sd.name), "%s %s %d-%4.4x",
|
||||
sensor->minfo.name, _this->name,
|
||||
i2c_adapter_id(client->adapter), client->addr);
|
||||
|
||||
this->sink_fmt.width =
|
||||
sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
|
||||
|
|
@ -2674,6 +2676,7 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
|||
try_fmt->width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
|
||||
try_fmt->height = sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
|
||||
try_fmt->code = mbus_code;
|
||||
try_fmt->field = V4L2_FIELD_NONE;
|
||||
|
||||
try_crop->top = 0;
|
||||
try_crop->left = 0;
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
if (ctrl->val <= ctrl->default_value) {
|
||||
/* Pack it into 0..1 step 0.125, register values 0..8 */
|
||||
unsigned long range = ctrl->default_value - ctrl->minimum;
|
||||
data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
|
||||
data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
|
||||
|
||||
dev_dbg(&client->dev, "Setting gain %d\n", data);
|
||||
data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
|
||||
|
|
@ -413,7 +413,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
/* Pack it into 1.125..15 variable step, register values 9..67 */
|
||||
/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
|
||||
unsigned long range = ctrl->maximum - ctrl->default_value - 1;
|
||||
unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
|
||||
unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
|
||||
111 + range / 2) / range + 9;
|
||||
|
||||
if (gain <= 32)
|
||||
|
|
@ -434,7 +434,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
case V4L2_CID_EXPOSURE_AUTO:
|
||||
if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
|
||||
unsigned long range = exp->maximum - exp->minimum;
|
||||
unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
|
||||
unsigned long shutter = ((exp->val - (s32)exp->minimum) * 1048 +
|
||||
range / 2) / range + 1;
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
|
|
|
|||
|
|
@ -931,6 +931,12 @@ static int mt9m111_probe(struct i2c_client *client,
|
|||
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
|
||||
int ret;
|
||||
|
||||
if (client->dev.of_node) {
|
||||
ssdd = devm_kzalloc(&client->dev, sizeof(*ssdd), GFP_KERNEL);
|
||||
if (!ssdd)
|
||||
return -ENOMEM;
|
||||
client->dev.platform_data = ssdd;
|
||||
}
|
||||
if (!ssdd) {
|
||||
dev_err(&client->dev, "mt9m111: driver needs platform data\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -1015,6 +1021,11 @@ static int mt9m111_remove(struct i2c_client *client)
|
|||
|
||||
return 0;
|
||||
}
|
||||
static const struct of_device_id mt9m111_of_match[] = {
|
||||
{ .compatible = "micron,mt9m111", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mt9m111_of_match);
|
||||
|
||||
static const struct i2c_device_id mt9m111_id[] = {
|
||||
{ "mt9m111", 0 },
|
||||
|
|
@ -1025,6 +1036,7 @@ MODULE_DEVICE_TABLE(i2c, mt9m111_id);
|
|||
static struct i2c_driver mt9m111_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "mt9m111",
|
||||
.of_match_table = of_match_ptr(mt9m111_of_match),
|
||||
},
|
||||
.probe = mt9m111_probe,
|
||||
.remove = mt9m111_remove,
|
||||
|
|
|
|||
|
|
@ -474,7 +474,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
if (ctrl->val <= ctrl->default_value) {
|
||||
/* Pack it into 0..1 step 0.125, register values 0..8 */
|
||||
unsigned long range = ctrl->default_value - ctrl->minimum;
|
||||
data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
|
||||
data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
|
||||
|
||||
dev_dbg(&client->dev, "Setting gain %d\n", data);
|
||||
data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
|
||||
|
|
@ -485,7 +485,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
|
||||
unsigned long range = ctrl->maximum - ctrl->default_value - 1;
|
||||
/* calculated gain: map 65..127 to 9..1024 step 0.125 */
|
||||
unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
|
||||
unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
|
||||
1015 + range / 2) / range + 9;
|
||||
|
||||
if (gain <= 32) /* calculated gain 9..32 -> 9..32 */
|
||||
|
|
@ -507,7 +507,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
case V4L2_CID_EXPOSURE_AUTO:
|
||||
if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
|
||||
unsigned int range = exp->maximum - exp->minimum;
|
||||
unsigned int shutter = ((exp->val - exp->minimum) * 1048 +
|
||||
unsigned int shutter = ((exp->val - (s32)exp->minimum) * 1048 +
|
||||
range / 2) / range + 1;
|
||||
u32 old;
|
||||
|
||||
|
|
|
|||
|
|
@ -583,7 +583,7 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
/* mt9v022 has minimum == default */
|
||||
unsigned long range = gain->maximum - gain->minimum;
|
||||
/* Valid values 16 to 64, 32 to 64 must be even. */
|
||||
unsigned long gain_val = ((gain->val - gain->minimum) *
|
||||
unsigned long gain_val = ((gain->val - (s32)gain->minimum) *
|
||||
48 + range / 2) / range + 16;
|
||||
|
||||
if (gain_val >= 32)
|
||||
|
|
@ -608,7 +608,7 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
} else {
|
||||
struct v4l2_ctrl *exp = mt9v022->exposure;
|
||||
unsigned long range = exp->maximum - exp->minimum;
|
||||
unsigned long shutter = ((exp->val - exp->minimum) *
|
||||
unsigned long shutter = ((exp->val - (s32)exp->minimum) *
|
||||
479 + range / 2) / range + 1;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -56,38 +56,29 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
|
|||
static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
|
||||
{
|
||||
struct i2c_client *c = v4l2_get_subdevdata(sd);
|
||||
unsigned char buffer[1];
|
||||
int rc;
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = c->addr, .flags = 0,
|
||||
.buf = &addr, .len = 1 },
|
||||
{ .addr = c->addr, .flags = I2C_M_RD,
|
||||
.buf = buffer, .len = 1 }
|
||||
};
|
||||
|
||||
rc = i2c_transfer(c->adapter, msg, 2);
|
||||
if (rc < 0 || rc != 2) {
|
||||
v4l2_err(sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
|
||||
return rc < 0 ? rc : -EIO;
|
||||
rc = i2c_smbus_read_byte_data(c, addr);
|
||||
if (rc < 0) {
|
||||
v4l2_err(sd, "i2c i/o error: rc == %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
|
||||
v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, rc);
|
||||
|
||||
return (buffer[0]);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
|
||||
unsigned char value)
|
||||
{
|
||||
struct i2c_client *c = v4l2_get_subdevdata(sd);
|
||||
unsigned char buffer[2];
|
||||
int rc;
|
||||
|
||||
buffer[0] = addr;
|
||||
buffer[1] = value;
|
||||
v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
|
||||
if (2 != (rc = i2c_master_send(c, buffer, 2)))
|
||||
v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
|
||||
v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", addr, value);
|
||||
rc = i2c_smbus_write_byte_data(c, addr, value);
|
||||
if (rc < 0)
|
||||
v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d\n", rc);
|
||||
}
|
||||
|
||||
static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
|
||||
|
|
@ -1148,10 +1139,10 @@ static int tvp5150_probe(struct i2c_client *c,
|
|||
/* Is TVP5150A */
|
||||
if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) {
|
||||
v4l2_info(sd, "tvp%02x%02xa detected.\n",
|
||||
tvp5150_id[2], tvp5150_id[3]);
|
||||
tvp5150_id[0], tvp5150_id[1]);
|
||||
} else {
|
||||
v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
|
||||
tvp5150_id[2], tvp5150_id[3]);
|
||||
tvp5150_id[0], tvp5150_id[1]);
|
||||
v4l2_info(sd, "*** Rom ver is %d.%d\n",
|
||||
tvp5150_id[2], tvp5150_id[3]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,8 +106,6 @@ static long media_device_enum_entities(struct media_device *mdev,
|
|||
if (ent->name) {
|
||||
strncpy(u_ent.name, ent->name, sizeof(u_ent.name));
|
||||
u_ent.name[sizeof(u_ent.name) - 1] = '\0';
|
||||
} else {
|
||||
memset(u_ent.name, 0, sizeof(u_ent.name));
|
||||
}
|
||||
u_ent.type = ent->type;
|
||||
u_ent.revision = ent->revision;
|
||||
|
|
|
|||
|
|
@ -759,7 +759,6 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
|
|||
pix->sizeimage = pix->width * pix->height;
|
||||
/* Just a guess */
|
||||
pix->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
pix->priv = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -785,7 +784,6 @@ static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format
|
|||
pix->sizeimage = pix->width * pix->height;
|
||||
/* Just a guess */
|
||||
pix->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
pix->priv = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -990,7 +988,6 @@ static struct qcam *qcam_init(struct parport *port)
|
|||
qcam->vdev.fops = &qcam_fops;
|
||||
qcam->vdev.lock = &qcam->lock;
|
||||
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
|
||||
qcam->vdev.release = video_device_release_empty;
|
||||
video_set_drvdata(&qcam->vdev, qcam);
|
||||
|
||||
|
|
|
|||
|
|
@ -761,7 +761,6 @@ static struct qcam *qcam_init(struct parport *port)
|
|||
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
|
||||
qcam->vdev.release = video_device_release_empty;
|
||||
qcam->vdev.ctrl_handler = &qcam->hdl;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
|
||||
video_set_drvdata(&qcam->vdev, qcam);
|
||||
|
||||
mutex_init(&qcam->lock);
|
||||
|
|
|
|||
|
|
@ -1091,7 +1091,6 @@ static int pms_probe(struct device *pdev, unsigned int card)
|
|||
dev->vdev.release = video_device_release_empty;
|
||||
dev->vdev.lock = &dev->lock;
|
||||
dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
|
||||
video_set_drvdata(&dev->vdev, dev);
|
||||
dev->std = V4L2_STD_NTSC_M;
|
||||
dev->height = 240;
|
||||
|
|
|
|||
|
|
@ -883,7 +883,6 @@ static int w9966_init(struct w9966 *cam, struct parport *port)
|
|||
cam->vdev.ioctl_ops = &w9966_ioctl_ops;
|
||||
cam->vdev.release = video_device_release_empty;
|
||||
cam->vdev.ctrl_handler = &cam->hdl;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
|
||||
video_set_drvdata(&cam->vdev, cam);
|
||||
|
||||
mutex_init(&cam->lock);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ if MEDIA_ANALOG_TV_SUPPORT
|
|||
source "drivers/media/pci/ivtv/Kconfig"
|
||||
source "drivers/media/pci/zoran/Kconfig"
|
||||
source "drivers/media/pci/saa7146/Kconfig"
|
||||
source "drivers/media/pci/solo6x10/Kconfig"
|
||||
endif
|
||||
|
||||
if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
|
||||
|
|
|
|||
|
|
@ -24,3 +24,4 @@ obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
|
|||
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
|
||||
obj-$(CONFIG_VIDEO_MEYE) += meye/
|
||||
obj-$(CONFIG_STA2X11_VIP) += sta2x11/
|
||||
obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/
|
||||
|
|
|
|||
|
|
@ -3886,7 +3886,6 @@ static struct video_device *vdev_init(struct bttv *btv,
|
|||
vfd->v4l2_dev = &btv->c.v4l2_dev;
|
||||
vfd->release = video_device_release;
|
||||
vfd->debug = bttv_debug;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
|
||||
video_set_drvdata(vfd, btv);
|
||||
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
|
||||
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
|
||||
|
|
|
|||
|
|
@ -73,12 +73,12 @@ static void ir_handle_key(struct bttv *btv)
|
|||
|
||||
if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
|
||||
(ir->mask_keyup && !(gpio & ir->mask_keyup))) {
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
} else {
|
||||
/* HACK: Probably, ir->mask_keydown is missing
|
||||
for this board */
|
||||
if (btv->c.type == BTTV_BOARD_WINFAST2000)
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
|
||||
rc_keyup(ir->dev);
|
||||
}
|
||||
|
|
@ -103,7 +103,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
|
|||
gpio, data,
|
||||
(gpio & ir->mask_keyup) ? " up" : "up/down");
|
||||
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
if (keyup)
|
||||
rc_keyup(ir->dev);
|
||||
} else {
|
||||
|
|
@ -117,7 +117,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
|
|||
if (keyup)
|
||||
rc_keyup(ir->dev);
|
||||
else
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
}
|
||||
|
||||
ir->last_gpio = data | keyup;
|
||||
|
|
@ -154,10 +154,10 @@ static void bttv_input_timer(unsigned long data)
|
|||
* testing.
|
||||
*/
|
||||
|
||||
#define RC5_START(x) (((x) >> 12) & 3)
|
||||
#define RC5_TOGGLE(x) (((x) >> 11) & 1)
|
||||
#define RC5_ADDR(x) (((x) >> 6) & 31)
|
||||
#define RC5_INSTR(x) ((x) & 63)
|
||||
#define RC5_START(x) (((x) >> 12) & 0x03)
|
||||
#define RC5_TOGGLE(x) (((x) >> 11) & 0x01)
|
||||
#define RC5_ADDR(x) (((x) >> 6) & 0x1f)
|
||||
#define RC5_INSTR(x) (((x) >> 0) & 0x3f)
|
||||
|
||||
/* decode raw bit pattern to RC5 code */
|
||||
static u32 bttv_rc5_decode(unsigned int code)
|
||||
|
|
@ -195,8 +195,8 @@ static void bttv_rc5_timer_end(unsigned long data)
|
|||
{
|
||||
struct bttv_ir *ir = (struct bttv_ir *)data;
|
||||
struct timeval tv;
|
||||
u32 gap;
|
||||
u32 rc5 = 0;
|
||||
u32 gap, rc5, scancode;
|
||||
u8 toggle, command, system;
|
||||
|
||||
/* get time */
|
||||
do_gettimeofday(&tv);
|
||||
|
|
@ -221,26 +221,29 @@ static void bttv_rc5_timer_end(unsigned long data)
|
|||
if (ir->last_bit < 20) {
|
||||
/* ignore spurious codes (caused by light/other remotes) */
|
||||
dprintk("short code: %x\n", ir->code);
|
||||
} else {
|
||||
ir->code = (ir->code << ir->shift_by) | 1;
|
||||
rc5 = bttv_rc5_decode(ir->code);
|
||||
|
||||
/* two start bits? */
|
||||
if (RC5_START(rc5) != ir->start) {
|
||||
pr_info(DEVNAME ":"
|
||||
" rc5 start bits invalid: %u\n", RC5_START(rc5));
|
||||
|
||||
/* right address? */
|
||||
} else if (RC5_ADDR(rc5) == ir->addr) {
|
||||
u32 toggle = RC5_TOGGLE(rc5);
|
||||
u32 instr = RC5_INSTR(rc5);
|
||||
|
||||
/* Good code */
|
||||
rc_keydown(ir->dev, instr, toggle);
|
||||
dprintk("instruction %x, toggle %x\n",
|
||||
instr, toggle);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ir->code = (ir->code << ir->shift_by) | 1;
|
||||
rc5 = bttv_rc5_decode(ir->code);
|
||||
|
||||
toggle = RC5_TOGGLE(rc5);
|
||||
system = RC5_ADDR(rc5);
|
||||
command = RC5_INSTR(rc5);
|
||||
|
||||
switch (RC5_START(rc5)) {
|
||||
case 0x3:
|
||||
break;
|
||||
case 0x2:
|
||||
command += 0x40;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
scancode = RC_SCANCODE_RC5(system, command);
|
||||
rc_keydown(ir->dev, RC_TYPE_RC5, scancode, toggle);
|
||||
dprintk("scancode %x, toggle %x\n", scancode, toggle);
|
||||
}
|
||||
|
||||
static int bttv_rc5_irq(struct bttv *btv)
|
||||
|
|
@ -310,8 +313,6 @@ static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
|
|||
/* set timer_end for code completion */
|
||||
setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
|
||||
ir->shift_by = 1;
|
||||
ir->start = 3;
|
||||
ir->addr = 0x0;
|
||||
ir->rc5_remote_gap = ir_rc5_remote_gap;
|
||||
}
|
||||
}
|
||||
|
|
@ -335,7 +336,8 @@ static void bttv_ir_stop(struct bttv *btv)
|
|||
* Get_key functions used by I2C remotes
|
||||
*/
|
||||
|
||||
static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_pv951(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char b;
|
||||
|
||||
|
|
@ -362,8 +364,9 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
* the device is bound to the vendor-provided RC.
|
||||
*/
|
||||
|
||||
*ir_key = b;
|
||||
*ir_raw = b;
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = b;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -490,8 +493,8 @@ int bttv_input_init(struct bttv *btv)
|
|||
ir->polling = 50; // ms
|
||||
break;
|
||||
case BTTV_BOARD_NEBULA_DIGITV:
|
||||
ir_codes = RC_MAP_NEBULA;
|
||||
ir->rc5_gpio = true;
|
||||
ir_codes = RC_MAP_NEBULA;
|
||||
ir->rc5_gpio = true;
|
||||
break;
|
||||
case BTTV_BOARD_MACHTV_MAGICTV:
|
||||
ir_codes = RC_MAP_APAC_VIEWCOMP;
|
||||
|
|
@ -514,7 +517,8 @@ int bttv_input_init(struct bttv *btv)
|
|||
ir->mask_keycode);
|
||||
break;
|
||||
}
|
||||
if (NULL == ir_codes) {
|
||||
|
||||
if (!ir_codes) {
|
||||
dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
|
||||
err = -ENODEV;
|
||||
goto err_out_free;
|
||||
|
|
|
|||
|
|
@ -133,8 +133,6 @@ struct bttv_ir {
|
|||
u32 polling;
|
||||
u32 last_gpio;
|
||||
int shift_by;
|
||||
int start; // What should RC5_START() be
|
||||
int addr; // What RC5_ADDR() should be.
|
||||
int rc5_remote_gap;
|
||||
|
||||
/* RC5 gpio */
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc)
|
|||
mutex_unlock(&cx->serialize_lock);
|
||||
}
|
||||
|
||||
#define CX18_ALSA_DBGFLG_WARN (1 << 0)
|
||||
#define CX18_ALSA_DBGFLG_WARN (1 << 0)
|
||||
#define CX18_ALSA_DBGFLG_INFO (1 << 1)
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
|
|||
pixfmt->height = cx->cxhdl.height;
|
||||
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
pixfmt->field = V4L2_FIELD_INTERLACED;
|
||||
pixfmt->priv = 0;
|
||||
if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
|
||||
pixfmt->pixelformat = s->pixelformat;
|
||||
pixfmt->sizeimage = s->vb_bytes_per_frame;
|
||||
|
|
|
|||
|
|
@ -375,7 +375,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
|
|||
s->video_dev->release = video_device_release;
|
||||
s->video_dev->tvnorms = V4L2_STD_ALL;
|
||||
s->video_dev->lock = &cx->serialize_lock;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
|
||||
cx18_set_funcs(s->video_dev);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,12 +31,14 @@ config VIDEO_CX23885
|
|||
select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_SI2165 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 DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
|
||||
---help---
|
||||
This is a video4linux driver for Conexant 23885 based
|
||||
TV cards.
|
||||
|
|
|
|||
|
|
@ -1266,7 +1266,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
|
|||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
if (UNSET == dev->tuner_type)
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
if (0 != t->index)
|
||||
return -EINVAL;
|
||||
|
|
@ -1284,7 +1284,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
|
|||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
if (UNSET == dev->tuner_type)
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
|
||||
/* Update the A/V core */
|
||||
|
|
@ -1299,7 +1299,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
|
|||
struct cx23885_fh *fh = file->private_data;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
if (UNSET == dev->tuner_type)
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
f->type = V4L2_TUNER_ANALOG_TV;
|
||||
f->frequency = dev->freq;
|
||||
|
|
@ -1347,7 +1347,7 @@ static int vidioc_querycap(struct file *file, void *priv,
|
|||
V4L2_CAP_READWRITE |
|
||||
V4L2_CAP_STREAMING |
|
||||
0;
|
||||
if (UNSET != dev->tuner_type)
|
||||
if (dev->tuner_type != TUNER_ABSENT)
|
||||
cap->capabilities |= V4L2_CAP_TUNER;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -619,7 +619,12 @@ struct cx23885_board cx23885_boards[] = {
|
|||
},
|
||||
[CX23885_BOARD_HAUPPAUGE_HVR4400] = {
|
||||
.name = "Hauppauge WinTV-HVR4400",
|
||||
.porta = CX23885_ANALOG_VIDEO,
|
||||
.portb = CX23885_MPEG_DVB,
|
||||
.portc = CX23885_MPEG_DVB,
|
||||
.tuner_type = TUNER_NXP_TDA18271,
|
||||
.tuner_addr = 0x60, /* 0xc0 >> 1 */
|
||||
.tuner_bus = 1,
|
||||
},
|
||||
[CX23885_BOARD_AVERMEDIA_HC81R] = {
|
||||
.name = "AVerTV Hybrid Express Slim HC81R",
|
||||
|
|
@ -649,7 +654,31 @@ struct cx23885_board cx23885_boards[] = {
|
|||
CX25840_NONE1_CH3,
|
||||
.amux = CX25840_AUDIO6,
|
||||
} },
|
||||
}
|
||||
},
|
||||
[CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2] = {
|
||||
.name = "DViCO FusionHDTV DVB-T Dual Express2",
|
||||
.portb = CX23885_MPEG_DVB,
|
||||
.portc = CX23885_MPEG_DVB,
|
||||
},
|
||||
[CX23885_BOARD_HAUPPAUGE_IMPACTVCBE] = {
|
||||
.name = "Hauppauge ImpactVCB-e",
|
||||
.tuner_type = TUNER_ABSENT,
|
||||
.porta = CX23885_ANALOG_VIDEO,
|
||||
.input = {{
|
||||
.type = CX23885_VMUX_COMPOSITE1,
|
||||
.vmux = CX25840_VIN7_CH3 |
|
||||
CX25840_VIN4_CH2 |
|
||||
CX25840_VIN6_CH1,
|
||||
.amux = CX25840_AUDIO7,
|
||||
}, {
|
||||
.type = CX23885_VMUX_SVIDEO,
|
||||
.vmux = CX25840_VIN7_CH3 |
|
||||
CX25840_VIN4_CH2 |
|
||||
CX25840_VIN8_CH1 |
|
||||
CX25840_SVIDEO_ON,
|
||||
.amux = CX25840_AUDIO7,
|
||||
} },
|
||||
},
|
||||
};
|
||||
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
|
||||
|
||||
|
|
@ -897,6 +926,14 @@ struct cx23885_subid cx23885_subids[] = {
|
|||
.subvendor = 0x1461,
|
||||
.subdevice = 0xd939,
|
||||
.card = CX23885_BOARD_AVERMEDIA_HC81R,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x7133,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_IMPACTVCBE,
|
||||
}, {
|
||||
.subvendor = 0x18ac,
|
||||
.subdevice = 0xdb98,
|
||||
.card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2,
|
||||
},
|
||||
};
|
||||
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
|
||||
|
|
@ -977,6 +1014,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
|
|||
case 71009:
|
||||
/* WinTV-HVR1200 (PCIe, Retail, full height)
|
||||
* DVB-T and basic analog */
|
||||
case 71100:
|
||||
/* WinTV-ImpactVCB-e (PCIe, Retail, half height)
|
||||
* Basic analog */
|
||||
case 71359:
|
||||
/* WinTV-HVR1200 (PCIe, OEM, half height)
|
||||
* DVB-T and basic analog */
|
||||
|
|
@ -1137,6 +1177,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
|
|||
break;
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
|
||||
/* Two identical tuners on two different i2c buses,
|
||||
* we need to reset the correct gpio. */
|
||||
if (port->nr == 1)
|
||||
|
|
@ -1280,6 +1321,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
|
|||
cx_set(GP0_IO, 0x000f000f);
|
||||
break;
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
|
||||
/* GPIO-0 portb xc3028 reset */
|
||||
/* GPIO-1 portb zl10353 reset */
|
||||
/* GPIO-2 portc xc3028 reset */
|
||||
|
|
@ -1449,13 +1491,16 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
|
|||
break;
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR4400:
|
||||
/* GPIO-8 tda10071 demod reset */
|
||||
/* GPIO-9 si2165 demod reset */
|
||||
|
||||
/* Put the parts into reset and back */
|
||||
cx23885_gpio_enable(dev, GPIO_8, 1);
|
||||
cx23885_gpio_clear(dev, GPIO_8);
|
||||
cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1);
|
||||
|
||||
cx23885_gpio_clear(dev, GPIO_8 | GPIO_9);
|
||||
mdelay(100);
|
||||
cx23885_gpio_set(dev, GPIO_8);
|
||||
cx23885_gpio_set(dev, GPIO_8 | GPIO_9);
|
||||
mdelay(100);
|
||||
|
||||
break;
|
||||
case CX23885_BOARD_AVERMEDIA_HC81R:
|
||||
cx_clear(MC417_CTL, 1);
|
||||
|
|
@ -1585,6 +1630,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
|
|||
ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
|
||||
break;
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
|
||||
request_module("ir-kbd-i2c");
|
||||
break;
|
||||
}
|
||||
|
|
@ -1701,6 +1747,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
|||
case CX23885_BOARD_HAUPPAUGE_HVR1850:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1290:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR4400:
|
||||
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
|
||||
if (dev->i2c_bus[0].i2c_rc == 0)
|
||||
hauppauge_eeprom(dev, eeprom+0xc0);
|
||||
break;
|
||||
|
|
@ -1720,6 +1767,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
|||
break;
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
|
||||
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
|
||||
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
|
|
@ -1799,6 +1847,9 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
|||
ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
|
||||
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
|
||||
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
break;
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1250:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1500:
|
||||
|
|
@ -1807,6 +1858,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
|||
case CX23885_BOARD_HAUPPAUGE_HVR1200:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1700:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1400:
|
||||
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
|
||||
|
|
@ -1835,6 +1887,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
|||
break;
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1250:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1800:
|
||||
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1700:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "tuner-xc2028.h"
|
||||
#include "tuner-simple.h"
|
||||
#include "dib7000p.h"
|
||||
#include "dib0070.h"
|
||||
#include "dibx000_common.h"
|
||||
#include "zl10353.h"
|
||||
#include "stv0900.h"
|
||||
|
|
@ -71,6 +72,7 @@
|
|||
#include "tda10071.h"
|
||||
#include "a8293.h"
|
||||
#include "mb86a20s.h"
|
||||
#include "si2165.h"
|
||||
|
||||
static unsigned int debug;
|
||||
|
||||
|
|
@ -302,6 +304,11 @@ static struct tda18271_config hauppauge_hvr1210_tuner_config = {
|
|||
.output_opt = TDA18271_OUTPUT_LT_OFF,
|
||||
};
|
||||
|
||||
static struct tda18271_config hauppauge_hvr4400_tuner_config = {
|
||||
.gate = TDA18271_GATE_DIGITAL,
|
||||
.output_opt = TDA18271_OUTPUT_LT_OFF,
|
||||
};
|
||||
|
||||
static struct tda18271_std_map hauppauge_hvr127x_std_map = {
|
||||
.atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4,
|
||||
.if_lvl = 1, .rfagc_top = 0x58 },
|
||||
|
|
@ -702,6 +709,12 @@ static const struct a8293_config hauppauge_a8293_config = {
|
|||
.i2c_addr = 0x0b,
|
||||
};
|
||||
|
||||
static const struct si2165_config hauppauge_hvr4400_si2165_config = {
|
||||
.i2c_addr = 0x64,
|
||||
.chip_mode = SI2165_MODE_PLL_XTAL,
|
||||
.ref_freq_Hz = 16000000,
|
||||
};
|
||||
|
||||
static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
|
||||
{
|
||||
struct cx23885_dev *dev = (struct cx23885_dev *)device;
|
||||
|
|
@ -746,8 +759,108 @@ static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
|
|||
return 0;
|
||||
};
|
||||
|
||||
static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
struct dib7000p_ops *dib7000p_ops = fe->sec_priv;
|
||||
|
||||
return dib7000p_ops->set_gpio(fe, 8, 0, !onoff);
|
||||
}
|
||||
|
||||
static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dib0070_config dib7070p_dib0070_config = {
|
||||
.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
|
||||
.reset = dib7070_tuner_reset,
|
||||
.sleep = dib7070_tuner_sleep,
|
||||
.clock_khz = 12000,
|
||||
.freq_offset_khz_vhf = 550,
|
||||
/* .flip_chip = 1, */
|
||||
};
|
||||
|
||||
/* DIB7070 generic */
|
||||
static struct dibx000_agc_config dib7070_agc_config = {
|
||||
.band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
|
||||
|
||||
/*
|
||||
* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5,
|
||||
* P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
|
||||
* P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0
|
||||
*/
|
||||
.setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) |
|
||||
(0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
|
||||
.inv_gain = 600,
|
||||
.time_stabiliz = 10,
|
||||
.alpha_level = 0,
|
||||
.thlock = 118,
|
||||
.wbd_inv = 0,
|
||||
.wbd_ref = 3530,
|
||||
.wbd_sel = 1,
|
||||
.wbd_alpha = 5,
|
||||
.agc1_max = 65535,
|
||||
.agc1_min = 0,
|
||||
.agc2_max = 65535,
|
||||
.agc2_min = 0,
|
||||
.agc1_pt1 = 0,
|
||||
.agc1_pt2 = 40,
|
||||
.agc1_pt3 = 183,
|
||||
.agc1_slope1 = 206,
|
||||
.agc1_slope2 = 255,
|
||||
.agc2_pt1 = 72,
|
||||
.agc2_pt2 = 152,
|
||||
.agc2_slope1 = 88,
|
||||
.agc2_slope2 = 90,
|
||||
.alpha_mant = 17,
|
||||
.alpha_exp = 27,
|
||||
.beta_mant = 23,
|
||||
.beta_exp = 51,
|
||||
.perform_agc_softsplit = 0,
|
||||
};
|
||||
|
||||
static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
|
||||
.internal = 60000,
|
||||
.sampling = 15000,
|
||||
.pll_prediv = 1,
|
||||
.pll_ratio = 20,
|
||||
.pll_range = 3,
|
||||
.pll_reset = 1,
|
||||
.pll_bypass = 0,
|
||||
.enable_refdiv = 0,
|
||||
.bypclk_div = 0,
|
||||
.IO_CLK_en_core = 1,
|
||||
.ADClkSrc = 1,
|
||||
.modulo = 2,
|
||||
/* refsel, sel, freq_15k */
|
||||
.sad_cfg = (3 << 14) | (1 << 12) | (524 << 0),
|
||||
.ifreq = (0 << 25) | 0,
|
||||
.timf = 20452225,
|
||||
.xtal_hz = 12000000,
|
||||
};
|
||||
|
||||
static struct dib7000p_config dib7070p_dib7000p_config = {
|
||||
/* .output_mode = OUTMODE_MPEG2_FIFO, */
|
||||
.output_mode = OUTMODE_MPEG2_SERIAL,
|
||||
/* .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, */
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
|
||||
.agc_config_count = 1,
|
||||
.agc = &dib7070_agc_config,
|
||||
.bw = &dib7070_bw_config_12_mhz,
|
||||
.tuner_is_baseband = 1,
|
||||
.spur_protect = 1,
|
||||
|
||||
.gpio_dir = 0xfcef, /* DIB7000P_GPIO_DEFAULT_DIRECTIONS, */
|
||||
.gpio_val = 0x0110, /* DIB7000P_GPIO_DEFAULT_VALUES, */
|
||||
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
|
||||
|
||||
.hostbus_diversity = 1,
|
||||
};
|
||||
|
||||
static int dvb_register(struct cx23885_tsport *port)
|
||||
{
|
||||
struct dib7000p_ops dib7000p_ops;
|
||||
struct cx23885_dev *dev = port->dev;
|
||||
struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
|
||||
struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
|
||||
|
|
@ -925,8 +1038,11 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
break;
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1400:
|
||||
i2c_bus = &dev->i2c_bus[0];
|
||||
fe0->dvb.frontend = dvb_attach(dib7000p_attach,
|
||||
&i2c_bus->i2c_adap,
|
||||
|
||||
if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
|
||||
return -ENODEV;
|
||||
|
||||
fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap,
|
||||
0x12, &hauppauge_hvr1400_dib7000_config);
|
||||
if (fe0->dvb.frontend != NULL) {
|
||||
struct dvb_frontend *fe;
|
||||
|
|
@ -989,6 +1105,30 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2: {
|
||||
i2c_bus = &dev->i2c_bus[port->nr - 1];
|
||||
/* cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); */
|
||||
/* cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); */
|
||||
|
||||
if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
|
||||
return -ENODEV;
|
||||
|
||||
if (dib7000p_ops.i2c_enumeration(&i2c_bus->i2c_adap, 1, 0x12, &dib7070p_dib7000p_config) < 0) {
|
||||
printk(KERN_WARNING "Unable to enumerate dib7000p\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap, 0x80, &dib7070p_dib7000p_config);
|
||||
if (fe0->dvb.frontend != NULL) {
|
||||
struct i2c_adapter *tun_i2c;
|
||||
|
||||
fe0->dvb.frontend->sec_priv = kmalloc(sizeof(dib7000p_ops), GFP_KERNEL);
|
||||
memcpy(fe0->dvb.frontend->sec_priv, &dib7000p_ops, sizeof(dib7000p_ops));
|
||||
tun_i2c = dib7000p_ops.get_i2c_master(fe0->dvb.frontend, DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
if (!dvb_attach(dib0070_attach, fe0->dvb.frontend, tun_i2c, &dib7070p_dib0070_config))
|
||||
return -ENODEV;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
|
||||
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
|
||||
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
|
||||
|
|
@ -1331,13 +1471,34 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
break;
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR4400:
|
||||
i2c_bus = &dev->i2c_bus[0];
|
||||
fe0->dvb.frontend = dvb_attach(tda10071_attach,
|
||||
i2c_bus2 = &dev->i2c_bus[1];
|
||||
switch (port->nr) {
|
||||
/* port b */
|
||||
case 1:
|
||||
fe0->dvb.frontend = dvb_attach(tda10071_attach,
|
||||
&hauppauge_tda10071_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
if (fe0->dvb.frontend != NULL) {
|
||||
dvb_attach(a8293_attach, fe0->dvb.frontend,
|
||||
&i2c_bus->i2c_adap,
|
||||
&hauppauge_a8293_config);
|
||||
if (fe0->dvb.frontend != NULL) {
|
||||
if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
|
||||
&i2c_bus->i2c_adap,
|
||||
&hauppauge_a8293_config))
|
||||
goto frontend_detach;
|
||||
}
|
||||
break;
|
||||
/* port c */
|
||||
case 2:
|
||||
fe0->dvb.frontend = dvb_attach(si2165_attach,
|
||||
&hauppauge_hvr4400_si2165_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
if (fe0->dvb.frontend != NULL) {
|
||||
fe0->dvb.frontend->ops.i2c_gate_ctrl = 0;
|
||||
if (!dvb_attach(tda18271_attach,
|
||||
fe0->dvb.frontend,
|
||||
0x60, &i2c_bus2->i2c_adap,
|
||||
&hauppauge_hvr4400_tuner_config))
|
||||
goto frontend_detach;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
|
|||
}
|
||||
rc->dev.parent = &dev->pci->dev;
|
||||
rc->driver_type = driver_type;
|
||||
rc_set_allowed_protocols(rc, allowed_protos);
|
||||
rc->allowed_protocols = allowed_protos;
|
||||
rc->priv = kernel_ir;
|
||||
rc->open = cx23885_input_ir_open;
|
||||
rc->close = cx23885_input_ir_close;
|
||||
|
|
|
|||
|
|
@ -507,6 +507,7 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
|
|||
if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
|
||||
(dev->board == CX23885_BOARD_MPX885) ||
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_IMPACTVCBE) ||
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
|
||||
|
|
@ -1156,7 +1157,7 @@ static int vidioc_querycap(struct file *file, void *priv,
|
|||
V4L2_CAP_READWRITE |
|
||||
V4L2_CAP_STREAMING |
|
||||
V4L2_CAP_VBI_CAPTURE;
|
||||
if (UNSET != dev->tuner_type)
|
||||
if (dev->tuner_type != TUNER_ABSENT)
|
||||
cap->capabilities |= V4L2_CAP_TUNER;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1474,7 +1475,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
|
|||
{
|
||||
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
|
||||
|
||||
if (unlikely(UNSET == dev->tuner_type))
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
if (0 != t->index)
|
||||
return -EINVAL;
|
||||
|
|
@ -1490,7 +1491,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
|
|||
{
|
||||
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
|
||||
|
||||
if (UNSET == dev->tuner_type)
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
if (0 != t->index)
|
||||
return -EINVAL;
|
||||
|
|
@ -1506,7 +1507,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
|
|||
struct cx23885_fh *fh = priv;
|
||||
struct cx23885_dev *dev = fh->dev;
|
||||
|
||||
if (unlikely(UNSET == dev->tuner_type))
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
|
||||
/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
|
||||
|
|
@ -1522,7 +1523,7 @@ static int cx23885_set_freq(struct cx23885_dev *dev, const struct v4l2_frequency
|
|||
{
|
||||
struct v4l2_control ctrl;
|
||||
|
||||
if (unlikely(UNSET == dev->tuner_type))
|
||||
if (dev->tuner_type == TUNER_ABSENT)
|
||||
return -EINVAL;
|
||||
if (unlikely(f->tuner != 0))
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@
|
|||
#define CX23885_BOARD_TBS_6981 40
|
||||
#define CX23885_BOARD_TBS_6980 41
|
||||
#define CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 42
|
||||
#define CX23885_BOARD_HAUPPAUGE_IMPACTVCBE 43
|
||||
#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2 44
|
||||
|
||||
#define GPIO_0 0x00000001
|
||||
#define GPIO_1 0x00000002
|
||||
|
|
|
|||
|
|
@ -576,7 +576,6 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
|
|||
f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
|
||||
f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -615,7 +614,6 @@ static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
|||
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
|
||||
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -867,7 +865,6 @@ static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv,
|
|||
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
|
||||
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
f->fmt.pix.priv = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1109,7 +1106,6 @@ int cx25821_video_register(struct cx25821_dev *dev)
|
|||
else
|
||||
vdev->vfl_dir = VFL_DIR_TX;
|
||||
vdev->lock = &dev->lock;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
|
||||
snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
|
||||
video_set_drvdata(vdev, chan);
|
||||
|
||||
|
|
|
|||
|
|
@ -1045,7 +1045,6 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
|
|||
vfd->release = video_device_release;
|
||||
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
|
||||
core->name, type, core->board.name);
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
|
||||
return vfd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,25 +130,41 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
|
|||
|
||||
data = (data << 4) | ((gpio_key & 0xf0) >> 4);
|
||||
|
||||
rc_keydown(ir->dev, data, 0);
|
||||
rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
|
||||
} else if (ir->core->boardnr == CX88_BOARD_PROLINK_PLAYTVPVR ||
|
||||
ir->core->boardnr == CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO) {
|
||||
/* bit cleared on keydown, NEC scancode, 0xAAAACC, A = 0x866b */
|
||||
u16 addr;
|
||||
u8 cmd;
|
||||
u32 scancode;
|
||||
|
||||
addr = (data >> 8) & 0xffff;
|
||||
cmd = (data >> 0) & 0x00ff;
|
||||
scancode = RC_SCANCODE_NECX(addr, cmd);
|
||||
|
||||
if (0 == (gpio & ir->mask_keyup))
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_NEC, scancode, 0);
|
||||
else
|
||||
rc_keyup(ir->dev);
|
||||
|
||||
} else if (ir->mask_keydown) {
|
||||
/* bit set on keydown */
|
||||
if (gpio & ir->mask_keydown)
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
else
|
||||
rc_keyup(ir->dev);
|
||||
|
||||
} else if (ir->mask_keyup) {
|
||||
/* bit cleared on keydown */
|
||||
if (0 == (gpio & ir->mask_keyup))
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
else
|
||||
rc_keyup(ir->dev);
|
||||
|
||||
} else {
|
||||
/* can't distinguish keydown/up :-/ */
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
rc_keyup(ir->dev);
|
||||
}
|
||||
}
|
||||
|
|
@ -329,6 +345,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
|
|||
* 002-T mini RC, provided with newer PV hardware
|
||||
*/
|
||||
ir_codes = RC_MAP_PIXELVIEW_MK12;
|
||||
rc_type = RC_BIT_NEC;
|
||||
ir->gpio_addr = MO_GP1_IO;
|
||||
ir->mask_keyup = 0x80;
|
||||
ir->polling = 10; /* ms */
|
||||
|
|
@ -416,7 +433,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
|
|||
break;
|
||||
case CX88_BOARD_TWINHAN_VP1027_DVBS:
|
||||
ir_codes = RC_MAP_TWINHAN_VP1027_DVBS;
|
||||
rc_type = RC_BIT_NEC;
|
||||
ir->sampling = 0xff00; /* address */
|
||||
break;
|
||||
}
|
||||
|
|
@ -462,14 +478,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
|
|||
dev->priv = core;
|
||||
dev->open = cx88_ir_open;
|
||||
dev->close = cx88_ir_close;
|
||||
dev->scanmask = hardware_mask;
|
||||
dev->scancode_mask = hardware_mask;
|
||||
|
||||
if (ir->sampling) {
|
||||
dev->driver_type = RC_DRIVER_IR_RAW;
|
||||
dev->timeout = 10 * 1000 * 1000; /* 10 ms */
|
||||
} else {
|
||||
dev->driver_type = RC_DRIVER_SCANCODE;
|
||||
rc_set_allowed_protocols(dev, rc_type);
|
||||
dev->allowed_protocols = rc_type;
|
||||
}
|
||||
|
||||
ir->core = core;
|
||||
|
|
@ -539,7 +555,8 @@ void cx88_ir_irq(struct cx88_core *core)
|
|||
ir_raw_event_handle(ir->dev);
|
||||
}
|
||||
|
||||
static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_pvr2000(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
int flags, code;
|
||||
|
||||
|
|
@ -563,8 +580,9 @@ static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
|
||||
code & 0xff, flags & 0xff);
|
||||
|
||||
*ir_key = code & 0xff;
|
||||
*ir_raw = code;
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = code & 0xff;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1663,11 +1663,40 @@ static struct ddb_info ddb_octopus_le = {
|
|||
.port_num = 2,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octopus_mini = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus Mini",
|
||||
.port_num = 4,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_v6 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V6 DVB adapter",
|
||||
.port_num = 3,
|
||||
};
|
||||
static struct ddb_info ddb_v6_5 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Cine S2 V6.5 DVB adapter",
|
||||
.port_num = 4,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_dvbct = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices DVBCT V6.1 DVB adapter",
|
||||
.port_num = 3,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_satixS2v3 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Mystique SaTiX-S2 V3 DVB adapter",
|
||||
.port_num = 3,
|
||||
};
|
||||
|
||||
static struct ddb_info ddb_octopusv3 = {
|
||||
.type = DDB_OCTOPUS,
|
||||
.name = "Digital Devices Octopus V3 DVB adapter",
|
||||
.port_num = 4,
|
||||
};
|
||||
|
||||
#define DDVID 0xdd01 /* Digital Devices Vendor ID */
|
||||
|
||||
|
|
@ -1680,8 +1709,12 @@ static const struct pci_device_id ddb_id_tbl[] = {
|
|||
DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
|
||||
DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
|
||||
DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
|
||||
/* in case sub-ids got deleted in flash */
|
||||
DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
|
||||
{0}
|
||||
|
|
|
|||
|
|
@ -678,7 +678,8 @@ static void dm1105_emit_key(struct work_struct *work)
|
|||
|
||||
data = (ircom >> 8) & 0x7f;
|
||||
|
||||
rc_keydown(ir->dev, data, 0);
|
||||
/* FIXME: UNKNOWN because we don't generate a full NEC scancode (yet?) */
|
||||
rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
}
|
||||
|
||||
/* work handler */
|
||||
|
|
|
|||
|
|
@ -135,8 +135,8 @@ static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
|||
/* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME
|
||||
control cluster */
|
||||
case V4L2_CID_MPEG_VIDEO_DEC_PTS:
|
||||
return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64,
|
||||
&itv->ctrl_frame->val64);
|
||||
return ivtv_g_pts_frame(itv, itv->ctrl_pts->p_new.p_s64,
|
||||
itv->ctrl_frame->p_new.p_s64);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,8 @@ static const char * const hw_devicenames[] = {
|
|||
"ir_video", /* IVTV_HW_I2C_IR_RX_ADAPTEC */
|
||||
};
|
||||
|
||||
static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_adaptec(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char keybuf[4];
|
||||
|
||||
|
|
@ -167,9 +168,9 @@ static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
keybuf[2] &= 0x7f;
|
||||
keybuf[3] |= 0x80;
|
||||
|
||||
*ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
|
||||
*ir_raw = *ir_key;
|
||||
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -351,7 +351,6 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
|
|||
pixfmt->height = itv->cxhdl.height;
|
||||
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
pixfmt->field = V4L2_FIELD_INTERLACED;
|
||||
pixfmt->priv = 0;
|
||||
if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
|
||||
pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
|
||||
/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
|
||||
|
|
@ -418,7 +417,6 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
|
|||
pixfmt->height = itv->main_rect.height;
|
||||
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
pixfmt->field = V4L2_FIELD_INTERLACED;
|
||||
pixfmt->priv = 0;
|
||||
if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
|
||||
switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
|
||||
case IVTV_YUV_MODE_INTERLACED:
|
||||
|
|
@ -1384,7 +1382,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
|
|||
fb->fmt.bytesperline = fb->fmt.width;
|
||||
fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
fb->fmt.field = V4L2_FIELD_INTERLACED;
|
||||
fb->fmt.priv = 0;
|
||||
if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
|
||||
fb->fmt.bytesperline *= 2;
|
||||
if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
|
||||
|
|
|
|||
|
|
@ -251,7 +251,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
|
|||
v4l2_disable_ioctl(s->vdev, VIDIOC_G_TUNER);
|
||||
v4l2_disable_ioctl(s->vdev, VIDIOC_S_STD);
|
||||
}
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
|
||||
ivtv_set_funcs(s->vdev);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1166,7 +1166,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
|
|||
f->fmt.pix.sizeimage = f->fmt.pix.height *
|
||||
f->fmt.pix.bytesperline;
|
||||
f->fmt.pix.colorspace = 0;
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1232,7 +1231,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
|
|||
f->fmt.pix.sizeimage = f->fmt.pix.height *
|
||||
f->fmt.pix.bytesperline;
|
||||
f->fmt.pix.colorspace = 0;
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1749,7 +1747,6 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
|
|||
|
||||
v4l2_ctrl_handler_setup(&meye.hdl);
|
||||
meye.vdev->ctrl_handler = &meye.hdl;
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &meye.vdev->flags);
|
||||
|
||||
if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
|
||||
video_nr) < 0) {
|
||||
|
|
|
|||
|
|
@ -910,7 +910,6 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev,
|
|||
{
|
||||
dma_addr_t tmp;
|
||||
u32 i, j;
|
||||
int status = 0;
|
||||
u32 SCListMemSize = pRingBuffer->NumBuffers
|
||||
* ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) :
|
||||
NUM_SCATTER_GATHER_ENTRIES)
|
||||
|
|
@ -1010,14 +1009,12 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev,
|
|||
|
||||
}
|
||||
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
|
||||
struct SRingBufferDescriptor *pRingBuffer)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
/* Copy pointer to scatter gather list in TSRingbuffer
|
||||
structure for buffer 2
|
||||
Load number of buffer
|
||||
|
|
@ -1038,7 +1035,7 @@ static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
|
|||
pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1;
|
||||
Cur = Cur->Next;
|
||||
}
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 RingBufferSizes[MAX_STREAM] = {
|
||||
|
|
|
|||
|
|
@ -811,7 +811,6 @@ static struct video_device *vdev_init(struct saa7134_dev *dev,
|
|||
vfd->release = video_device_release;
|
||||
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
|
||||
dev->name, type, saa7134_boards[dev->board].name);
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
|
||||
video_set_drvdata(vfd, dev);
|
||||
return vfd;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
|
|||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -148,7 +147,6 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
|
|||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -166,7 +164,6 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
|
|||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -270,7 +267,6 @@ static int empress_init(struct saa7134_dev *dev)
|
|||
snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
|
||||
"%s empress (%s)", dev->name,
|
||||
saa7134_boards[dev->board].name);
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &dev->empress_dev->flags);
|
||||
v4l2_ctrl_handler_init(hdl, 21);
|
||||
v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
|
||||
if (dev->empress_sd)
|
||||
|
|
|
|||
|
|
@ -83,14 +83,14 @@ static int build_key(struct saa7134_dev *dev)
|
|||
if (data == ir->mask_keycode)
|
||||
rc_keyup(ir->dev);
|
||||
else
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ir->polling) {
|
||||
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
|
||||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
} else {
|
||||
rc_keyup(ir->dev);
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ static int build_key(struct saa7134_dev *dev)
|
|||
else { /* IRQ driven mode - handle key press and release in one go */
|
||||
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
|
||||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
|
||||
rc_keydown_notimeout(ir->dev, data, 0);
|
||||
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
|
||||
rc_keyup(ir->dev);
|
||||
}
|
||||
}
|
||||
|
|
@ -108,7 +108,8 @@ static int build_key(struct saa7134_dev *dev)
|
|||
|
||||
/* --------------------- Chip specific I2C key builders ----------------- */
|
||||
|
||||
static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
int gpio;
|
||||
int attempt = 0;
|
||||
|
|
@ -132,10 +133,6 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
if (0x40000 & ~gpio)
|
||||
return 0; /* No button press */
|
||||
|
||||
/* No button press - only before first key pressed */
|
||||
if (b == 0xFF)
|
||||
return 0;
|
||||
|
||||
/* poll IR chip */
|
||||
/* weak up the IR chip */
|
||||
b = 0;
|
||||
|
|
@ -158,13 +155,14 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
*ir_key = b;
|
||||
*ir_raw = b;
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = b;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
|
||||
u32 *ir_raw)
|
||||
static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char b;
|
||||
int gpio;
|
||||
|
|
@ -205,14 +203,15 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
|
|||
/* Button pressed */
|
||||
|
||||
dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
|
||||
*ir_key = b;
|
||||
*ir_raw = b;
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = b;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* copied and modified from get_key_msi_tvanywhere_plus() */
|
||||
static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
|
||||
u32 *ir_raw)
|
||||
static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char b;
|
||||
unsigned int gpio;
|
||||
|
|
@ -253,12 +252,14 @@ static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
|
|||
/* Button pressed */
|
||||
|
||||
dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b);
|
||||
*ir_key = b;
|
||||
*ir_raw = b;
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = b;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_purpletv(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char b;
|
||||
|
||||
|
|
@ -276,12 +277,14 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
if (b & 0x80)
|
||||
return 1;
|
||||
|
||||
*ir_key = b;
|
||||
*ir_raw = b;
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = b;
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_hvr1110(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char buf[5];
|
||||
|
||||
|
|
@ -299,14 +302,20 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
* by preserving it into two separate readings
|
||||
* buf[4] bits 0 and 1, and buf[1] and buf[2] are always
|
||||
* zero.
|
||||
*
|
||||
* Note that the keymap which the hvr1110 uses is RC5.
|
||||
*
|
||||
* FIXME: start bits could maybe be used...?
|
||||
*/
|
||||
*ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2));
|
||||
*ir_raw = *ir_key;
|
||||
*protocol = RC_TYPE_RC5;
|
||||
*scancode = RC_SCANCODE_RC5(buf[3] & 0x1f, buf[4] >> 2);
|
||||
*toggle = !!(buf[3] & 0x40);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_beholdm6xx(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
unsigned char data[12];
|
||||
u32 gpio;
|
||||
|
|
@ -332,17 +341,18 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
if (data[9] != (unsigned char)(~data[8]))
|
||||
return 0;
|
||||
|
||||
*ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0));
|
||||
*ir_key = *ir_raw;
|
||||
|
||||
*protocol = RC_TYPE_NEC;
|
||||
*scancode = RC_SCANCODE_NECX(data[11] << 8 | data[10], data[9]);
|
||||
*toggle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Common (grey or coloured) pinnacle PCTV remote handling
|
||||
*
|
||||
*/
|
||||
static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
|
||||
int parity_offset, int marker, int code_modulo)
|
||||
static int get_key_pinnacle(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle, int parity_offset,
|
||||
int marker, int code_modulo)
|
||||
{
|
||||
unsigned char b[4];
|
||||
unsigned int start = 0,parity = 0,code = 0;
|
||||
|
|
@ -377,11 +387,11 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
|
|||
|
||||
code %= code_modulo;
|
||||
|
||||
*ir_raw = code;
|
||||
*ir_key = code;
|
||||
*protocol = RC_TYPE_UNKNOWN;
|
||||
*scancode = code;
|
||||
*toggle = 0;
|
||||
|
||||
i2cdprintk("Pinnacle PCTV key %02x\n", code);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -394,10 +404,11 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
|
|||
*
|
||||
* Sylvain Pasche <sylvain.pasche@gmail.com>
|
||||
*/
|
||||
static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_pinnacle_grey(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
|
||||
return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
|
||||
return get_key_pinnacle(ir, protocol, scancode, toggle, 1, 0xfe, 0xff);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -405,7 +416,8 @@ static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
*
|
||||
* Ricardo Cerqueira <v4l@cerqueira.org>
|
||||
*/
|
||||
static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
static int get_key_pinnacle_color(struct IR_i2c *ir, enum rc_type *protocol,
|
||||
u32 *scancode, u8 *toggle)
|
||||
{
|
||||
/* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
|
||||
*
|
||||
|
|
@ -413,7 +425,7 @@ static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
* codes < 128
|
||||
*/
|
||||
|
||||
return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
|
||||
return get_key_pinnacle(ir, protocol, scancode, toggle, 2, 0x80, 0x88);
|
||||
}
|
||||
|
||||
void saa7134_input_irq(struct saa7134_dev *dev)
|
||||
|
|
|
|||
|
|
@ -1235,7 +1235,6 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
|
|||
f->fmt.pix.sizeimage =
|
||||
f->fmt.pix.height * f->fmt.pix.bytesperline;
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
f->fmt.pix.priv = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1315,7 +1314,6 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
|
|||
f->fmt.pix.sizeimage =
|
||||
f->fmt.pix.height * f->fmt.pix.bytesperline;
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,16 +242,14 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
|
|||
if (!demux->dmx.frontend)
|
||||
return -EINVAL;
|
||||
|
||||
if (dvb) {
|
||||
mutex_lock(&dvb->lock);
|
||||
if (dvb->feeding++ == 0) {
|
||||
/* Start transport */
|
||||
ret = saa7164_dvb_start_port(port);
|
||||
}
|
||||
mutex_unlock(&dvb->lock);
|
||||
dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
|
||||
__func__, port->nr, dvb->feeding);
|
||||
mutex_lock(&dvb->lock);
|
||||
if (dvb->feeding++ == 0) {
|
||||
/* Start transport */
|
||||
ret = saa7164_dvb_start_port(port);
|
||||
}
|
||||
mutex_unlock(&dvb->lock);
|
||||
dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
|
||||
__func__, port->nr, dvb->feeding);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -266,16 +264,14 @@ static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
|
|||
|
||||
dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
|
||||
|
||||
if (dvb) {
|
||||
mutex_lock(&dvb->lock);
|
||||
if (--dvb->feeding == 0) {
|
||||
/* Stop transport */
|
||||
ret = saa7164_dvb_stop_streaming(port);
|
||||
}
|
||||
mutex_unlock(&dvb->lock);
|
||||
dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
|
||||
__func__, port->nr, dvb->feeding);
|
||||
mutex_lock(&dvb->lock);
|
||||
if (--dvb->feeding == 0) {
|
||||
/* Stop transport */
|
||||
ret = saa7164_dvb_stop_streaming(port);
|
||||
}
|
||||
mutex_unlock(&dvb->lock);
|
||||
dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
|
||||
__func__, port->nr, dvb->feeding);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
19
drivers/media/pci/solo6x10/Kconfig
Normal file
19
drivers/media/pci/solo6x10/Kconfig
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
config VIDEO_SOLO6X10
|
||||
tristate "Bluecherry / Softlogic 6x10 capture cards (MPEG-4/H.264)"
|
||||
depends on PCI && VIDEO_DEV && SND && I2C
|
||||
select BITREVERSE
|
||||
select FONT_SUPPORT
|
||||
select FONT_8x16
|
||||
select VIDEOBUF2_DMA_SG
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
select SND_PCM
|
||||
select FONT_8x16
|
||||
---help---
|
||||
This driver supports the Bluecherry H.264 and MPEG-4 hardware
|
||||
compression capture cards and other Softlogic-based ones.
|
||||
|
||||
Following cards have been tested:
|
||||
* Bluecherry BC-H16480A (PCIe, 16 port, H.264)
|
||||
* Bluecherry BC-H04120A (PCIe, 4 port, H.264)
|
||||
* Bluecherry BC-H04120A-MPCI (Mini-PCI, 4 port, H.264)
|
||||
* Bluecherry BC-04120A (PCIe, 4 port, MPEG-4)
|
||||
5
drivers/media/pci/solo6x10/Makefile
Normal file
5
drivers/media/pci/solo6x10/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
solo6x10-y := solo6x10-core.o solo6x10-i2c.o solo6x10-p2m.o solo6x10-v4l2.o \
|
||||
solo6x10-tw28.o solo6x10-gpio.o solo6x10-disp.o solo6x10-enc.o \
|
||||
solo6x10-v4l2-enc.o solo6x10-g723.o solo6x10-eeprom.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10.o
|
||||
705
drivers/media/pci/solo6x10/solo6x10-core.c
Normal file
705
drivers/media/pci/solo6x10/solo6x10-core.c
Normal file
|
|
@ -0,0 +1,705 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
|
||||
*
|
||||
* Original author:
|
||||
* Ben Collins <bcollins@ubuntu.com>
|
||||
*
|
||||
* Additional work by:
|
||||
* John Brooks <john.brooks@bluecherry.net>
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "solo6x10.h"
|
||||
#include "solo6x10-tw28.h"
|
||||
|
||||
MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver");
|
||||
MODULE_AUTHOR("Bluecherry <[email protected]>");
|
||||
MODULE_VERSION(SOLO6X10_VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned video_nr = -1;
|
||||
module_param(video_nr, uint, 0644);
|
||||
MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
|
||||
|
||||
static int full_eeprom; /* default is only top 64B */
|
||||
module_param(full_eeprom, uint, 0644);
|
||||
MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)");
|
||||
|
||||
|
||||
static void solo_set_time(struct solo_dev *solo_dev)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
ktime_get_ts(&ts);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec);
|
||||
solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC);
|
||||
}
|
||||
|
||||
static void solo_timer_sync(struct solo_dev *solo_dev)
|
||||
{
|
||||
u32 sec, usec;
|
||||
struct timespec ts;
|
||||
long diff;
|
||||
|
||||
if (solo_dev->type != SOLO_DEV_6110)
|
||||
return;
|
||||
|
||||
if (++solo_dev->time_sync < 60)
|
||||
return;
|
||||
|
||||
solo_dev->time_sync = 0;
|
||||
|
||||
sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC);
|
||||
usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC);
|
||||
|
||||
ktime_get_ts(&ts);
|
||||
|
||||
diff = (long)ts.tv_sec - (long)sec;
|
||||
diff = (diff * 1000000)
|
||||
+ ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec);
|
||||
|
||||
if (diff > 1000 || diff < -1000) {
|
||||
solo_set_time(solo_dev);
|
||||
} else if (diff) {
|
||||
long usec_lsb = solo_dev->usec_lsb;
|
||||
|
||||
usec_lsb -= diff / 4;
|
||||
if (usec_lsb < 0)
|
||||
usec_lsb = 0;
|
||||
else if (usec_lsb > 255)
|
||||
usec_lsb = 255;
|
||||
|
||||
solo_dev->usec_lsb = usec_lsb;
|
||||
solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB,
|
||||
solo_dev->usec_lsb);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t solo_isr(int irq, void *data)
|
||||
{
|
||||
struct solo_dev *solo_dev = data;
|
||||
u32 status;
|
||||
int i;
|
||||
|
||||
status = solo_reg_read(solo_dev, SOLO_IRQ_STAT);
|
||||
if (!status)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (status & ~solo_dev->irq_mask) {
|
||||
solo_reg_write(solo_dev, SOLO_IRQ_STAT,
|
||||
status & ~solo_dev->irq_mask);
|
||||
status &= solo_dev->irq_mask;
|
||||
}
|
||||
|
||||
if (status & SOLO_IRQ_PCI_ERR)
|
||||
solo_p2m_error_isr(solo_dev);
|
||||
|
||||
for (i = 0; i < SOLO_NR_P2M; i++)
|
||||
if (status & SOLO_IRQ_P2M(i))
|
||||
solo_p2m_isr(solo_dev, i);
|
||||
|
||||
if (status & SOLO_IRQ_IIC)
|
||||
solo_i2c_isr(solo_dev);
|
||||
|
||||
if (status & SOLO_IRQ_VIDEO_IN) {
|
||||
solo_video_in_isr(solo_dev);
|
||||
solo_timer_sync(solo_dev);
|
||||
}
|
||||
|
||||
if (status & SOLO_IRQ_ENCODER)
|
||||
solo_enc_v4l2_isr(solo_dev);
|
||||
|
||||
if (status & SOLO_IRQ_G723)
|
||||
solo_g723_isr(solo_dev);
|
||||
|
||||
/* Clear all interrupts handled */
|
||||
solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void free_solo_dev(struct solo_dev *solo_dev)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (!solo_dev)
|
||||
return;
|
||||
|
||||
if (solo_dev->dev.parent)
|
||||
device_unregister(&solo_dev->dev);
|
||||
|
||||
pdev = solo_dev->pdev;
|
||||
|
||||
/* If we never initialized the PCI device, then nothing else
|
||||
* below here needs cleanup */
|
||||
if (!pdev) {
|
||||
kfree(solo_dev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (solo_dev->reg_base) {
|
||||
/* Bring down the sub-devices first */
|
||||
solo_g723_exit(solo_dev);
|
||||
solo_enc_v4l2_exit(solo_dev);
|
||||
solo_enc_exit(solo_dev);
|
||||
solo_v4l2_exit(solo_dev);
|
||||
solo_disp_exit(solo_dev);
|
||||
solo_gpio_exit(solo_dev);
|
||||
solo_p2m_exit(solo_dev);
|
||||
solo_i2c_exit(solo_dev);
|
||||
|
||||
/* Now cleanup the PCI device */
|
||||
solo_irq_off(solo_dev, ~0);
|
||||
pci_iounmap(pdev, solo_dev->reg_base);
|
||||
if (pdev->irq)
|
||||
free_irq(pdev->irq, solo_dev);
|
||||
}
|
||||
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
v4l2_device_unregister(&solo_dev->v4l2_dev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
||||
kfree(solo_dev);
|
||||
}
|
||||
|
||||
static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
unsigned short *p = (unsigned short *)buf;
|
||||
int i;
|
||||
|
||||
if (count & 0x1)
|
||||
dev_warn(dev, "EEPROM Write not aligned (truncating)\n");
|
||||
|
||||
if (!full_eeprom && count > 64) {
|
||||
dev_warn(dev, "EEPROM Write truncated to 64 bytes\n");
|
||||
count = 64;
|
||||
} else if (full_eeprom && count > 128) {
|
||||
dev_warn(dev, "EEPROM Write truncated to 128 bytes\n");
|
||||
count = 128;
|
||||
}
|
||||
|
||||
solo_eeprom_ewen(solo_dev, 1);
|
||||
|
||||
for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32),
|
||||
(int)(count / 2)); i++)
|
||||
solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i]));
|
||||
|
||||
solo_eeprom_ewen(solo_dev, 0);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
unsigned short *p = (unsigned short *)buf;
|
||||
int count = (full_eeprom ? 128 : 64);
|
||||
int i;
|
||||
|
||||
for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++)
|
||||
p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i));
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t p2m_timeouts_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
|
||||
return sprintf(buf, "%d\n", solo_dev->p2m_timeouts);
|
||||
}
|
||||
|
||||
static ssize_t sdram_size_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
|
||||
return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20);
|
||||
}
|
||||
|
||||
static ssize_t tw28xx_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
|
||||
return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n",
|
||||
hweight32(solo_dev->tw2815),
|
||||
hweight32(solo_dev->tw2864),
|
||||
hweight32(solo_dev->tw2865));
|
||||
}
|
||||
|
||||
static ssize_t input_map_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
unsigned int val;
|
||||
char *out = buf;
|
||||
|
||||
val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0);
|
||||
out += sprintf(out, "Channel 0 => Input %d\n", val & 0x1f);
|
||||
out += sprintf(out, "Channel 1 => Input %d\n", (val >> 5) & 0x1f);
|
||||
out += sprintf(out, "Channel 2 => Input %d\n", (val >> 10) & 0x1f);
|
||||
out += sprintf(out, "Channel 3 => Input %d\n", (val >> 15) & 0x1f);
|
||||
out += sprintf(out, "Channel 4 => Input %d\n", (val >> 20) & 0x1f);
|
||||
out += sprintf(out, "Channel 5 => Input %d\n", (val >> 25) & 0x1f);
|
||||
|
||||
val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1);
|
||||
out += sprintf(out, "Channel 6 => Input %d\n", val & 0x1f);
|
||||
out += sprintf(out, "Channel 7 => Input %d\n", (val >> 5) & 0x1f);
|
||||
out += sprintf(out, "Channel 8 => Input %d\n", (val >> 10) & 0x1f);
|
||||
out += sprintf(out, "Channel 9 => Input %d\n", (val >> 15) & 0x1f);
|
||||
out += sprintf(out, "Channel 10 => Input %d\n", (val >> 20) & 0x1f);
|
||||
out += sprintf(out, "Channel 11 => Input %d\n", (val >> 25) & 0x1f);
|
||||
|
||||
val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2);
|
||||
out += sprintf(out, "Channel 12 => Input %d\n", val & 0x1f);
|
||||
out += sprintf(out, "Channel 13 => Input %d\n", (val >> 5) & 0x1f);
|
||||
out += sprintf(out, "Channel 14 => Input %d\n", (val >> 10) & 0x1f);
|
||||
out += sprintf(out, "Channel 15 => Input %d\n", (val >> 15) & 0x1f);
|
||||
out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f);
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
static ssize_t p2m_timeout_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
unsigned long ms;
|
||||
int ret = kstrtoul(buf, 10, &ms);
|
||||
|
||||
if (ret < 0 || ms > 200)
|
||||
return -EINVAL;
|
||||
solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t p2m_timeout_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
|
||||
return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies));
|
||||
}
|
||||
|
||||
static ssize_t intervals_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
char *out = buf;
|
||||
int fps = solo_dev->fps;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < solo_dev->nr_chans; i++) {
|
||||
out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n",
|
||||
i, solo_dev->v4l2_enc[i]->interval, fps,
|
||||
solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i)));
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
static ssize_t sdram_offsets_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
char *out = buf;
|
||||
|
||||
out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n",
|
||||
SOLO_DISP_EXT_ADDR,
|
||||
SOLO_DISP_EXT_SIZE);
|
||||
|
||||
out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n",
|
||||
SOLO_EOSD_EXT_ADDR,
|
||||
SOLO_EOSD_EXT_AREA(solo_dev),
|
||||
SOLO_EOSD_EXT_SIZE(solo_dev),
|
||||
SOLO_EOSD_EXT_AREA(solo_dev) /
|
||||
SOLO_EOSD_EXT_SIZE(solo_dev));
|
||||
|
||||
out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n",
|
||||
SOLO_MOTION_EXT_ADDR(solo_dev),
|
||||
SOLO_MOTION_EXT_SIZE);
|
||||
|
||||
out += sprintf(out, "G723: 0x%08x @ 0x%08x\n",
|
||||
SOLO_G723_EXT_ADDR(solo_dev),
|
||||
SOLO_G723_EXT_SIZE);
|
||||
|
||||
out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n",
|
||||
SOLO_CAP_EXT_ADDR(solo_dev),
|
||||
SOLO_CAP_EXT_SIZE(solo_dev),
|
||||
SOLO_CAP_PAGE_SIZE,
|
||||
SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE);
|
||||
|
||||
out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n",
|
||||
SOLO_EREF_EXT_ADDR(solo_dev),
|
||||
SOLO_EREF_EXT_AREA(solo_dev),
|
||||
SOLO_EREF_EXT_SIZE,
|
||||
SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE);
|
||||
|
||||
out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n",
|
||||
SOLO_MP4E_EXT_ADDR(solo_dev),
|
||||
SOLO_MP4E_EXT_SIZE(solo_dev));
|
||||
|
||||
out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n",
|
||||
SOLO_JPEG_EXT_ADDR(solo_dev),
|
||||
SOLO_JPEG_EXT_SIZE(solo_dev));
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
static ssize_t sdram_show(struct file *file, struct kobject *kobj,
|
||||
struct bin_attribute *a, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct solo_dev *solo_dev =
|
||||
container_of(dev, struct solo_dev, dev);
|
||||
const int size = solo_dev->sdram_size;
|
||||
|
||||
if (off >= size)
|
||||
return 0;
|
||||
|
||||
if (off + count > size)
|
||||
count = size - off;
|
||||
|
||||
if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0))
|
||||
return -EIO;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct device_attribute solo_dev_attrs[] = {
|
||||
__ATTR(eeprom, 0640, eeprom_show, eeprom_store),
|
||||
__ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store),
|
||||
__ATTR_RO(p2m_timeouts),
|
||||
__ATTR_RO(sdram_size),
|
||||
__ATTR_RO(tw28xx),
|
||||
__ATTR_RO(input_map),
|
||||
__ATTR_RO(intervals),
|
||||
__ATTR_RO(sdram_offsets),
|
||||
};
|
||||
|
||||
static void solo_device_release(struct device *dev)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static int solo_sysfs_init(struct solo_dev *solo_dev)
|
||||
{
|
||||
struct bin_attribute *sdram_attr = &solo_dev->sdram_attr;
|
||||
struct device *dev = &solo_dev->dev;
|
||||
const char *driver;
|
||||
int i;
|
||||
|
||||
if (solo_dev->type == SOLO_DEV_6110)
|
||||
driver = "solo6110";
|
||||
else
|
||||
driver = "solo6010";
|
||||
|
||||
dev->release = solo_device_release;
|
||||
dev->parent = &solo_dev->pdev->dev;
|
||||
set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev));
|
||||
dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num,
|
||||
solo_dev->nr_chans);
|
||||
|
||||
if (device_register(dev)) {
|
||||
dev->parent = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) {
|
||||
if (device_create_file(dev, &solo_dev_attrs[i])) {
|
||||
device_unregister(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
sysfs_attr_init(&sdram_attr->attr);
|
||||
sdram_attr->attr.name = "sdram";
|
||||
sdram_attr->attr.mode = 0440;
|
||||
sdram_attr->read = sdram_show;
|
||||
sdram_attr->size = solo_dev->sdram_size;
|
||||
|
||||
if (device_create_bin_file(dev, sdram_attr)) {
|
||||
device_unregister(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct solo_dev *solo_dev;
|
||||
int ret;
|
||||
u8 chip_id;
|
||||
|
||||
solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
|
||||
if (solo_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (id->driver_data == SOLO_DEV_6010)
|
||||
dev_info(&pdev->dev, "Probing Softlogic 6010\n");
|
||||
else
|
||||
dev_info(&pdev->dev, "Probing Softlogic 6110\n");
|
||||
|
||||
solo_dev->type = id->driver_data;
|
||||
solo_dev->pdev = pdev;
|
||||
spin_lock_init(&solo_dev->reg_io_lock);
|
||||
ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
/* Only for during init */
|
||||
solo_dev->p2m_jiffies = msecs_to_jiffies(100);
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
/* RETRY/TRDY Timeout disabled */
|
||||
pci_write_config_byte(pdev, 0x40, 0x00);
|
||||
pci_write_config_byte(pdev, 0x41, 0x00);
|
||||
|
||||
ret = pci_request_regions(pdev, SOLO6X10_NAME);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
solo_dev->reg_base = pci_ioremap_bar(pdev, 0);
|
||||
if (solo_dev->reg_base == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_probe;
|
||||
}
|
||||
|
||||
chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) &
|
||||
SOLO_CHIP_ID_MASK;
|
||||
switch (chip_id) {
|
||||
case 7:
|
||||
solo_dev->nr_chans = 16;
|
||||
solo_dev->nr_ext = 5;
|
||||
break;
|
||||
case 6:
|
||||
solo_dev->nr_chans = 8;
|
||||
solo_dev->nr_ext = 2;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n",
|
||||
chip_id);
|
||||
case 5:
|
||||
solo_dev->nr_chans = 4;
|
||||
solo_dev->nr_ext = 1;
|
||||
}
|
||||
|
||||
/* Disable all interrupts to start */
|
||||
solo_irq_off(solo_dev, ~0);
|
||||
|
||||
/* Initial global settings */
|
||||
if (solo_dev->type == SOLO_DEV_6010) {
|
||||
solo_dev->clock_mhz = 108;
|
||||
solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT
|
||||
| SOLO_SYS_CFG_INPUTDIV(25)
|
||||
| SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2)
|
||||
| SOLO_SYS_CFG_OUTDIV(3);
|
||||
solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
|
||||
} else {
|
||||
u32 divq, divf;
|
||||
|
||||
solo_dev->clock_mhz = 135;
|
||||
|
||||
if (solo_dev->clock_mhz < 125) {
|
||||
divq = 3;
|
||||
divf = (solo_dev->clock_mhz * 4) / 3 - 1;
|
||||
} else {
|
||||
divq = 2;
|
||||
divf = (solo_dev->clock_mhz * 2) / 3 - 1;
|
||||
}
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_PLL_CONFIG,
|
||||
(1 << 20) | /* PLL_RANGE */
|
||||
(8 << 15) | /* PLL_DIVR */
|
||||
(divq << 12) |
|
||||
(divf << 4) |
|
||||
(1 << 1) /* PLL_FSEN */);
|
||||
|
||||
solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT;
|
||||
}
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
|
||||
solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM,
|
||||
solo_dev->clock_mhz - 1);
|
||||
|
||||
/* PLL locking time of 1ms */
|
||||
mdelay(1);
|
||||
|
||||
ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME,
|
||||
solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
/* Handle this from the start */
|
||||
solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR);
|
||||
|
||||
ret = solo_i2c_init(solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
/* Setup the DMA engine */
|
||||
solo_reg_write(solo_dev, SOLO_DMA_CTRL,
|
||||
SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
|
||||
SOLO_DMA_CTRL_SDRAM_SIZE(2) |
|
||||
SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
|
||||
SOLO_DMA_CTRL_READ_CLK_SELECT |
|
||||
SOLO_DMA_CTRL_LATENCY(1));
|
||||
|
||||
/* Undocumented crap */
|
||||
solo_reg_write(solo_dev, SOLO_DMA_CTRL1,
|
||||
solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300);
|
||||
|
||||
if (solo_dev->type != SOLO_DEV_6010) {
|
||||
solo_dev->usec_lsb = 0x3f;
|
||||
solo_set_time(solo_dev);
|
||||
}
|
||||
|
||||
/* Disable watchdog */
|
||||
solo_reg_write(solo_dev, SOLO_WATCHDOG, 0);
|
||||
|
||||
/* Initialize sub components */
|
||||
|
||||
ret = solo_p2m_init(solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
ret = solo_disp_init(solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
ret = solo_gpio_init(solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
ret = solo_tw28_init(solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
ret = solo_v4l2_init(solo_dev, video_nr);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
ret = solo_enc_init(solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
ret = solo_enc_v4l2_init(solo_dev, video_nr);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
ret = solo_g723_init(solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
ret = solo_sysfs_init(solo_dev);
|
||||
if (ret)
|
||||
goto fail_probe;
|
||||
|
||||
/* Now that init is over, set this lower */
|
||||
solo_dev->p2m_jiffies = msecs_to_jiffies(20);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_probe:
|
||||
free_solo_dev(solo_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void solo_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
|
||||
struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev);
|
||||
|
||||
free_solo_dev(solo_dev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id solo_id_table[] = {
|
||||
/* 6010 based cards */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010),
|
||||
.driver_data = SOLO_DEV_6010 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4),
|
||||
.driver_data = SOLO_DEV_6010 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9),
|
||||
.driver_data = SOLO_DEV_6010 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16),
|
||||
.driver_data = SOLO_DEV_6010 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4),
|
||||
.driver_data = SOLO_DEV_6010 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9),
|
||||
.driver_data = SOLO_DEV_6010 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16),
|
||||
.driver_data = SOLO_DEV_6010 },
|
||||
/* 6110 based cards */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110),
|
||||
.driver_data = SOLO_DEV_6110 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4),
|
||||
.driver_data = SOLO_DEV_6110 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8),
|
||||
.driver_data = SOLO_DEV_6110 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16),
|
||||
.driver_data = SOLO_DEV_6110 },
|
||||
{0,}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, solo_id_table);
|
||||
|
||||
static struct pci_driver solo_pci_driver = {
|
||||
.name = SOLO6X10_NAME,
|
||||
.id_table = solo_id_table,
|
||||
.probe = solo_pci_probe,
|
||||
.remove = solo_pci_remove,
|
||||
};
|
||||
|
||||
module_pci_driver(solo_pci_driver);
|
||||
322
drivers/media/pci/solo6x10/solo6x10-disp.c
Normal file
322
drivers/media/pci/solo6x10/solo6x10-disp.c
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
|
||||
*
|
||||
* Original author:
|
||||
* Ben Collins <bcollins@ubuntu.com>
|
||||
*
|
||||
* Additional work by:
|
||||
* John Brooks <john.brooks@bluecherry.net>
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
|
||||
#include "solo6x10.h"
|
||||
|
||||
#define SOLO_VCLK_DELAY 3
|
||||
#define SOLO_PROGRESSIVE_VSIZE 1024
|
||||
|
||||
#define SOLO_MOT_THRESH_W 64
|
||||
#define SOLO_MOT_THRESH_H 64
|
||||
#define SOLO_MOT_THRESH_SIZE 8192
|
||||
#define SOLO_MOT_THRESH_REAL (SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H)
|
||||
#define SOLO_MOT_FLAG_SIZE 1024
|
||||
#define SOLO_MOT_FLAG_AREA (SOLO_MOT_FLAG_SIZE * 16)
|
||||
|
||||
static void solo_vin_config(struct solo_dev *solo_dev)
|
||||
{
|
||||
solo_dev->vin_hstart = 8;
|
||||
solo_dev->vin_vstart = 2;
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_SYS_VCLK,
|
||||
SOLO_VCLK_SELECT(2) |
|
||||
SOLO_VCLK_VIN1415_DELAY(SOLO_VCLK_DELAY) |
|
||||
SOLO_VCLK_VIN1213_DELAY(SOLO_VCLK_DELAY) |
|
||||
SOLO_VCLK_VIN1011_DELAY(SOLO_VCLK_DELAY) |
|
||||
SOLO_VCLK_VIN0809_DELAY(SOLO_VCLK_DELAY) |
|
||||
SOLO_VCLK_VIN0607_DELAY(SOLO_VCLK_DELAY) |
|
||||
SOLO_VCLK_VIN0405_DELAY(SOLO_VCLK_DELAY) |
|
||||
SOLO_VCLK_VIN0203_DELAY(SOLO_VCLK_DELAY) |
|
||||
SOLO_VCLK_VIN0001_DELAY(SOLO_VCLK_DELAY));
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VI_ACT_I_P,
|
||||
SOLO_VI_H_START(solo_dev->vin_hstart) |
|
||||
SOLO_VI_V_START(solo_dev->vin_vstart) |
|
||||
SOLO_VI_V_STOP(solo_dev->vin_vstart +
|
||||
solo_dev->video_vsize));
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VI_ACT_I_S,
|
||||
SOLO_VI_H_START(solo_dev->vout_hstart) |
|
||||
SOLO_VI_V_START(solo_dev->vout_vstart) |
|
||||
SOLO_VI_V_STOP(solo_dev->vout_vstart +
|
||||
solo_dev->video_vsize));
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VI_ACT_P,
|
||||
SOLO_VI_H_START(0) |
|
||||
SOLO_VI_V_START(1) |
|
||||
SOLO_VI_V_STOP(SOLO_PROGRESSIVE_VSIZE));
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT,
|
||||
SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0));
|
||||
|
||||
/* On 6110, initialize mozaic darkness stength */
|
||||
if (solo_dev->type == SOLO_DEV_6010)
|
||||
solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0);
|
||||
else
|
||||
solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 16 << 22);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2);
|
||||
|
||||
if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
|
||||
solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
|
||||
SOLO_VI_PB_USER_MODE);
|
||||
solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
|
||||
SOLO_VI_PB_HSIZE(858) | SOLO_VI_PB_VSIZE(246));
|
||||
solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
|
||||
SOLO_VI_PB_VSTART(4) |
|
||||
SOLO_VI_PB_VSTOP(4 + 240));
|
||||
} else {
|
||||
solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
|
||||
SOLO_VI_PB_USER_MODE | SOLO_VI_PB_PAL);
|
||||
solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
|
||||
SOLO_VI_PB_HSIZE(864) | SOLO_VI_PB_VSIZE(294));
|
||||
solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
|
||||
SOLO_VI_PB_VSTART(4) |
|
||||
SOLO_VI_PB_VSTOP(4 + 288));
|
||||
}
|
||||
solo_reg_write(solo_dev, SOLO_VI_PB_ACT_H, SOLO_VI_PB_HSTART(16) |
|
||||
SOLO_VI_PB_HSTOP(16 + 720));
|
||||
}
|
||||
|
||||
static void solo_vout_config_cursor(struct solo_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Load (blank) cursor bitmap mask (2bpp) */
|
||||
for (i = 0; i < 20; i++)
|
||||
solo_reg_write(dev, SOLO_VO_CURSOR_MASK(i), 0);
|
||||
|
||||
solo_reg_write(dev, SOLO_VO_CURSOR_POS, 0);
|
||||
|
||||
solo_reg_write(dev, SOLO_VO_CURSOR_CLR,
|
||||
(0x80 << 24) | (0x80 << 16) | (0x10 << 8) | 0x80);
|
||||
solo_reg_write(dev, SOLO_VO_CURSOR_CLR2, (0xe0 << 8) | 0x80);
|
||||
}
|
||||
|
||||
static void solo_vout_config(struct solo_dev *solo_dev)
|
||||
{
|
||||
solo_dev->vout_hstart = 6;
|
||||
solo_dev->vout_vstart = 8;
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_FMT_ENC,
|
||||
solo_dev->video_type |
|
||||
SOLO_VO_USER_COLOR_SET_NAV |
|
||||
SOLO_VO_USER_COLOR_SET_NAH |
|
||||
SOLO_VO_NA_COLOR_Y(0) |
|
||||
SOLO_VO_NA_COLOR_CB(0) |
|
||||
SOLO_VO_NA_COLOR_CR(0));
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_ACT_H,
|
||||
SOLO_VO_H_START(solo_dev->vout_hstart) |
|
||||
SOLO_VO_H_STOP(solo_dev->vout_hstart +
|
||||
solo_dev->video_hsize));
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_ACT_V,
|
||||
SOLO_VO_V_START(solo_dev->vout_vstart) |
|
||||
SOLO_VO_V_STOP(solo_dev->vout_vstart +
|
||||
solo_dev->video_vsize));
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_RANGE_HV,
|
||||
SOLO_VO_H_LEN(solo_dev->video_hsize) |
|
||||
SOLO_VO_V_LEN(solo_dev->video_vsize));
|
||||
|
||||
/* Border & background colors */
|
||||
solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
|
||||
(0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
|
||||
solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
|
||||
(0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
|
||||
solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
|
||||
(16 << 24) | (128 << 16) | (16 << 8) | 128);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 0);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON |
|
||||
SOLO_VO_DISP_ERASE_COUNT(8) |
|
||||
SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR));
|
||||
|
||||
|
||||
solo_vout_config_cursor(solo_dev);
|
||||
|
||||
/* Enable channels we support */
|
||||
solo_reg_write(solo_dev, SOLO_VI_CH_ENA,
|
||||
(1 << solo_dev->nr_chans) - 1);
|
||||
}
|
||||
|
||||
static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
|
||||
u16 val, int reg_size)
|
||||
{
|
||||
u16 *buf;
|
||||
const int n = 64, size = n * sizeof(*buf);
|
||||
int i, ret = 0;
|
||||
|
||||
buf = kmalloc(size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
buf[i] = cpu_to_le16(val);
|
||||
|
||||
for (i = 0; i < reg_size; i += size) {
|
||||
ret = solo_p2m_dma(solo_dev, 1, buf,
|
||||
SOLO_MOTION_EXT_ADDR(solo_dev) + off + i,
|
||||
size, 0, 0);
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
|
||||
{
|
||||
if (ch > solo_dev->nr_chans)
|
||||
return -EINVAL;
|
||||
|
||||
return solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
|
||||
(ch * SOLO_MOT_THRESH_SIZE * 2),
|
||||
val, SOLO_MOT_THRESH_SIZE);
|
||||
}
|
||||
|
||||
int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
|
||||
const u16 *thresholds)
|
||||
{
|
||||
const unsigned size = sizeof(u16) * 64;
|
||||
u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
|
||||
u16 *buf;
|
||||
int x, y;
|
||||
int ret = 0;
|
||||
|
||||
buf = kzalloc(size, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
for (y = 0; y < SOLO_MOTION_SZ; y++) {
|
||||
for (x = 0; x < SOLO_MOTION_SZ; x++)
|
||||
buf[x] = cpu_to_le16(thresholds[y * SOLO_MOTION_SZ + x]);
|
||||
ret |= solo_p2m_dma(solo_dev, 1, buf,
|
||||
SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * size,
|
||||
size, 0, 0);
|
||||
}
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k
|
||||
* threshold and working table for each channel. Atleast that's what the
|
||||
* spec says. However, this code (taken from rdk) has some mystery 8k
|
||||
* block right after the flag area, before the first thresh table. */
|
||||
static void solo_motion_config(struct solo_dev *solo_dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < solo_dev->nr_chans; i++) {
|
||||
/* Clear motion flag area */
|
||||
solo_dma_vin_region(solo_dev, i * SOLO_MOT_FLAG_SIZE, 0x0000,
|
||||
SOLO_MOT_FLAG_SIZE);
|
||||
|
||||
/* Clear working cache table */
|
||||
solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
|
||||
(i * SOLO_MOT_THRESH_SIZE * 2) +
|
||||
SOLO_MOT_THRESH_SIZE, 0x0000,
|
||||
SOLO_MOT_THRESH_SIZE);
|
||||
|
||||
/* Set default threshold table */
|
||||
solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH);
|
||||
}
|
||||
|
||||
/* Default motion settings */
|
||||
solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
|
||||
(SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
|
||||
solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
|
||||
SOLO_VI_MOTION_FRAME_COUNT(3) |
|
||||
SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16)
|
||||
/* | SOLO_VI_MOTION_INTR_START_STOP */
|
||||
| SOLO_VI_MOTION_SAMPLE_COUNT(10));
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
|
||||
}
|
||||
|
||||
int solo_disp_init(struct solo_dev *solo_dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
solo_dev->video_hsize = 704;
|
||||
if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
|
||||
solo_dev->video_vsize = 240;
|
||||
solo_dev->fps = 30;
|
||||
} else {
|
||||
solo_dev->video_vsize = 288;
|
||||
solo_dev->fps = 25;
|
||||
}
|
||||
|
||||
solo_vin_config(solo_dev);
|
||||
solo_motion_config(solo_dev);
|
||||
solo_vout_config(solo_dev);
|
||||
|
||||
for (i = 0; i < solo_dev->nr_chans; i++)
|
||||
solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void solo_disp_exit(struct solo_dev *solo_dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
|
||||
|
||||
for (i = 0; i < solo_dev->nr_chans; i++) {
|
||||
solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(i), 0);
|
||||
solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(i), 0);
|
||||
solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 0);
|
||||
}
|
||||
|
||||
/* Set default border */
|
||||
for (i = 0; i < 5; i++)
|
||||
solo_reg_write(solo_dev, SOLO_VO_BORDER_X(i), 0);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
solo_reg_write(solo_dev, SOLO_VO_BORDER_Y(i), 0);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_MASK, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_MASK, 0);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(0), 0);
|
||||
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(0), 0);
|
||||
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(0), 0);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(1), 0);
|
||||
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(1), 0);
|
||||
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(1), 0);
|
||||
}
|
||||
150
drivers/media/pci/solo6x10/solo6x10-eeprom.c
Normal file
150
drivers/media/pci/solo6x10/solo6x10-eeprom.c
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
|
||||
*
|
||||
* Original author:
|
||||
* Ben Collins <bcollins@ubuntu.com>
|
||||
*
|
||||
* Additional work by:
|
||||
* John Brooks <john.brooks@bluecherry.net>
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "solo6x10.h"
|
||||
|
||||
/* Control */
|
||||
#define EE_SHIFT_CLK 0x04
|
||||
#define EE_CS 0x08
|
||||
#define EE_DATA_WRITE 0x02
|
||||
#define EE_DATA_READ 0x01
|
||||
#define EE_ENB (0x80 | EE_CS)
|
||||
|
||||
#define eeprom_delay() udelay(100)
|
||||
#if 0
|
||||
#define eeprom_delay() solo_reg_read(solo_dev, SOLO_EEPROM_CTRL)
|
||||
#define eeprom_delay() ({ \
|
||||
int i, ret; \
|
||||
udelay(100); \
|
||||
for (i = ret = 0; i < 1000 && !ret; i++) \
|
||||
ret = solo_eeprom_reg_read(solo_dev); \
|
||||
})
|
||||
#endif
|
||||
#define ADDR_LEN 6
|
||||
|
||||
/* Commands */
|
||||
#define EE_EWEN_CMD 4
|
||||
#define EE_EWDS_CMD 4
|
||||
#define EE_WRITE_CMD 5
|
||||
#define EE_READ_CMD 6
|
||||
#define EE_ERASE_CMD 7
|
||||
|
||||
static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev)
|
||||
{
|
||||
return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ;
|
||||
}
|
||||
|
||||
static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data)
|
||||
{
|
||||
solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
|
||||
eeprom_delay();
|
||||
}
|
||||
|
||||
static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN);
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
|
||||
|
||||
for (i = 4 + ADDR_LEN; i >= 0; i--) {
|
||||
int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
|
||||
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval);
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
|
||||
EE_SHIFT_CLK | dataval);
|
||||
}
|
||||
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
|
||||
}
|
||||
|
||||
unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
|
||||
{
|
||||
int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN);
|
||||
unsigned int retval = 0;
|
||||
int i;
|
||||
|
||||
solo_eeprom_cmd(solo_dev, ewen_cmd);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
|
||||
EE_SHIFT_CLK);
|
||||
retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
|
||||
retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
|
||||
}
|
||||
|
||||
solo_eeprom_reg_write(solo_dev, ~EE_CS);
|
||||
retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc)
|
||||
{
|
||||
int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
|
||||
unsigned short retval = 0;
|
||||
int i;
|
||||
|
||||
solo_eeprom_cmd(solo_dev, read_cmd);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
|
||||
EE_SHIFT_CLK);
|
||||
retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
|
||||
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
|
||||
}
|
||||
|
||||
solo_eeprom_reg_write(solo_dev, ~EE_CS);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
|
||||
unsigned short data)
|
||||
{
|
||||
int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN);
|
||||
unsigned int retval;
|
||||
int i;
|
||||
|
||||
solo_eeprom_cmd(solo_dev, write_cmd);
|
||||
|
||||
for (i = 15; i >= 0; i--) {
|
||||
unsigned int dataval = (data >> i) & 1;
|
||||
|
||||
solo_eeprom_reg_write(solo_dev, EE_ENB);
|
||||
solo_eeprom_reg_write(solo_dev,
|
||||
EE_ENB | (dataval << 1) | EE_SHIFT_CLK);
|
||||
}
|
||||
|
||||
solo_eeprom_reg_write(solo_dev, EE_ENB);
|
||||
solo_eeprom_reg_write(solo_dev, ~EE_CS);
|
||||
solo_eeprom_reg_write(solo_dev, EE_ENB);
|
||||
|
||||
for (i = retval = 0; i < 10000 && !retval; i++)
|
||||
retval = solo_eeprom_reg_read(solo_dev);
|
||||
|
||||
solo_eeprom_reg_write(solo_dev, ~EE_CS);
|
||||
|
||||
return !retval;
|
||||
}
|
||||
340
drivers/media/pci/solo6x10/solo6x10-enc.c
Normal file
340
drivers/media/pci/solo6x10/solo6x10-enc.c
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
|
||||
*
|
||||
* Original author:
|
||||
* Ben Collins <bcollins@ubuntu.com>
|
||||
*
|
||||
* Additional work by:
|
||||
* John Brooks <john.brooks@bluecherry.net>
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/font.h>
|
||||
#include <linux/bitrev.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "solo6x10.h"
|
||||
|
||||
#define VI_PROG_HSIZE (1280 - 16)
|
||||
#define VI_PROG_VSIZE (1024 - 16)
|
||||
|
||||
#define IRQ_LEVEL 2
|
||||
|
||||
static void solo_capture_config(struct solo_dev *solo_dev)
|
||||
{
|
||||
unsigned long height;
|
||||
unsigned long width;
|
||||
void *buf;
|
||||
int i;
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_CAP_BASE,
|
||||
SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
|
||||
- SOLO_CAP_PAGE_SIZE) >> 16)
|
||||
| SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
|
||||
|
||||
/* XXX: Undocumented bits at b17 and b24 */
|
||||
if (solo_dev->type == SOLO_DEV_6110) {
|
||||
/* NOTE: Ref driver has (62 << 24) here as well, but it causes
|
||||
* wacked out frame timing on 4-port 6110. */
|
||||
solo_reg_write(solo_dev, SOLO_CAP_BTW,
|
||||
(1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
|
||||
SOLO_CAP_MAX_BANDWIDTH(36));
|
||||
} else {
|
||||
solo_reg_write(solo_dev, SOLO_CAP_BTW,
|
||||
(1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
|
||||
SOLO_CAP_MAX_BANDWIDTH(32));
|
||||
}
|
||||
|
||||
/* Set scale 1, 9 dimension */
|
||||
width = solo_dev->video_hsize;
|
||||
height = solo_dev->video_vsize;
|
||||
solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
|
||||
SOLO_DIM_H_MB_NUM(width / 16) |
|
||||
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
|
||||
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
|
||||
|
||||
/* Set scale 2, 10 dimension */
|
||||
width = solo_dev->video_hsize / 2;
|
||||
height = solo_dev->video_vsize;
|
||||
solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
|
||||
SOLO_DIM_H_MB_NUM(width / 16) |
|
||||
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
|
||||
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
|
||||
|
||||
/* Set scale 3, 11 dimension */
|
||||
width = solo_dev->video_hsize / 2;
|
||||
height = solo_dev->video_vsize / 2;
|
||||
solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
|
||||
SOLO_DIM_H_MB_NUM(width / 16) |
|
||||
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
|
||||
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
|
||||
|
||||
/* Set scale 4, 12 dimension */
|
||||
width = solo_dev->video_hsize / 3;
|
||||
height = solo_dev->video_vsize / 3;
|
||||
solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
|
||||
SOLO_DIM_H_MB_NUM(width / 16) |
|
||||
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
|
||||
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
|
||||
|
||||
/* Set scale 5, 13 dimension */
|
||||
width = solo_dev->video_hsize / 4;
|
||||
height = solo_dev->video_vsize / 2;
|
||||
solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
|
||||
SOLO_DIM_H_MB_NUM(width / 16) |
|
||||
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
|
||||
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
|
||||
|
||||
/* Progressive */
|
||||
width = VI_PROG_HSIZE;
|
||||
height = VI_PROG_VSIZE;
|
||||
solo_reg_write(solo_dev, SOLO_DIM_PROG,
|
||||
SOLO_DIM_H_MB_NUM(width / 16) |
|
||||
SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
|
||||
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
|
||||
|
||||
/* Clear OSD */
|
||||
solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
|
||||
solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
|
||||
0xF0 << 16 | 0x80 << 8 | 0x80);
|
||||
|
||||
if (solo_dev->type == SOLO_DEV_6010)
|
||||
solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
|
||||
SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
|
||||
else
|
||||
solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
|
||||
| SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
|
||||
|
||||
/* Clear OSG buffer */
|
||||
buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
for (i = 0; i < solo_dev->nr_chans; i++) {
|
||||
solo_p2m_dma(solo_dev, 1, buf,
|
||||
SOLO_EOSD_EXT_ADDR +
|
||||
(SOLO_EOSD_EXT_SIZE(solo_dev) * i),
|
||||
SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
|
||||
}
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
#define SOLO_OSD_WRITE_SIZE (16 * OSD_TEXT_MAX)
|
||||
|
||||
/* Should be called with enable_lock held */
|
||||
int solo_osd_print(struct solo_enc_dev *solo_enc)
|
||||
{
|
||||
struct solo_dev *solo_dev = solo_enc->solo_dev;
|
||||
unsigned char *str = solo_enc->osd_text;
|
||||
u8 *buf = solo_enc->osd_buf;
|
||||
u32 reg;
|
||||
const struct font_desc *vga = find_font("VGA8x16");
|
||||
const unsigned char *vga_data;
|
||||
int i, j;
|
||||
|
||||
if (WARN_ON_ONCE(!vga))
|
||||
return -ENODEV;
|
||||
|
||||
reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
|
||||
if (!*str) {
|
||||
/* Disable OSD on this channel */
|
||||
reg &= ~(1 << solo_enc->ch);
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(buf, 0, SOLO_OSD_WRITE_SIZE);
|
||||
vga_data = (const unsigned char *)vga->data;
|
||||
|
||||
for (i = 0; *str; i++, str++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
buf[(j << 1) | (i & 1) | ((i & ~1) << 4)] =
|
||||
bitrev8(vga_data[(*str << 4) | j]);
|
||||
}
|
||||
}
|
||||
|
||||
solo_p2m_dma(solo_dev, 1, buf,
|
||||
SOLO_EOSD_EXT_ADDR_CHAN(solo_dev, solo_enc->ch),
|
||||
SOLO_OSD_WRITE_SIZE, 0, 0);
|
||||
|
||||
/* Enable OSD on this channel */
|
||||
reg |= (1 << solo_enc->ch);
|
||||
|
||||
out:
|
||||
solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel Quality Profile (0-3).
|
||||
*/
|
||||
void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
|
||||
unsigned int qp)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int idx, reg;
|
||||
|
||||
if ((ch > 31) || (qp > 3))
|
||||
return;
|
||||
|
||||
if (solo_dev->type == SOLO_DEV_6010)
|
||||
return;
|
||||
|
||||
if (ch < 16) {
|
||||
idx = 0;
|
||||
reg = SOLO_VE_JPEG_QP_CH_L;
|
||||
} else {
|
||||
ch -= 16;
|
||||
idx = 1;
|
||||
reg = SOLO_VE_JPEG_QP_CH_H;
|
||||
}
|
||||
ch *= 2;
|
||||
|
||||
spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
|
||||
|
||||
solo_dev->jpeg_qp[idx] &= ~(3 << ch);
|
||||
solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
|
||||
|
||||
solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
|
||||
|
||||
spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
|
||||
}
|
||||
|
||||
int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (solo_dev->type == SOLO_DEV_6010)
|
||||
return 2;
|
||||
|
||||
if (WARN_ON_ONCE(ch > 31))
|
||||
return 2;
|
||||
|
||||
if (ch < 16) {
|
||||
idx = 0;
|
||||
} else {
|
||||
ch -= 16;
|
||||
idx = 1;
|
||||
}
|
||||
ch *= 2;
|
||||
|
||||
return (solo_dev->jpeg_qp[idx] >> ch) & 3;
|
||||
}
|
||||
|
||||
#define SOLO_QP_INIT 0xaaaaaaaa
|
||||
|
||||
static void solo_jpeg_config(struct solo_dev *solo_dev)
|
||||
{
|
||||
if (solo_dev->type == SOLO_DEV_6010) {
|
||||
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
|
||||
(2 << 24) | (2 << 16) | (2 << 8) | 2);
|
||||
} else {
|
||||
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
|
||||
(4 << 24) | (3 << 16) | (2 << 8) | 1);
|
||||
}
|
||||
|
||||
spin_lock_init(&solo_dev->jpeg_qp_lock);
|
||||
|
||||
/* Initialize Quality Profile for all channels */
|
||||
solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
|
||||
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
|
||||
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
|
||||
(SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
|
||||
((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
|
||||
solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
|
||||
if (solo_dev->type == SOLO_DEV_6110) {
|
||||
solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
|
||||
(0 << 16) | (30 << 8) | 60);
|
||||
}
|
||||
}
|
||||
|
||||
static void solo_mp4e_config(struct solo_dev *solo_dev)
|
||||
{
|
||||
int i;
|
||||
u32 cfg;
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VE_CFG0,
|
||||
SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
|
||||
SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
|
||||
SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
|
||||
|
||||
|
||||
cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
|
||||
| SOLO_VE_MOTION_MODE(0);
|
||||
if (solo_dev->type != SOLO_DEV_6010) {
|
||||
cfg |= SOLO_VE_MPEG_SIZE_H(
|
||||
(SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
|
||||
cfg |= SOLO_VE_JPEG_SIZE_H(
|
||||
(SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
|
||||
}
|
||||
solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
|
||||
if (solo_dev->type == SOLO_DEV_6110)
|
||||
solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
|
||||
solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
|
||||
|
||||
solo_reg_write(solo_dev, SOLO_VE_ATTR,
|
||||
SOLO_VE_LITTLE_ENDIAN |
|
||||
SOLO_COMP_ATTR_FCODE(1) |
|
||||
SOLO_COMP_TIME_INC(0) |
|
||||
SOLO_COMP_TIME_WIDTH(15) |
|
||||
SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
|
||||
|
||||
for (i = 0; i < solo_dev->nr_chans; i++) {
|
||||
solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
|
||||
(SOLO_EREF_EXT_ADDR(solo_dev) +
|
||||
(i * SOLO_EREF_EXT_SIZE)) >> 16);
|
||||
solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
|
||||
(SOLO_EREF_EXT_ADDR(solo_dev) +
|
||||
((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
|
||||
}
|
||||
|
||||
if (solo_dev->type == SOLO_DEV_6110) {
|
||||
solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
|
||||
} else {
|
||||
for (i = 0; i < solo_dev->nr_chans; i++)
|
||||
solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
|
||||
}
|
||||
}
|
||||
|
||||
int solo_enc_init(struct solo_dev *solo_dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
solo_capture_config(solo_dev);
|
||||
solo_mp4e_config(solo_dev);
|
||||
solo_jpeg_config(solo_dev);
|
||||
|
||||
for (i = 0; i < solo_dev->nr_chans; i++) {
|
||||
solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
|
||||
solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void solo_enc_exit(struct solo_dev *solo_dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < solo_dev->nr_chans; i++) {
|
||||
solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
|
||||
solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue