Skip to content

Commit

Permalink
Merge branch 'media-fixes' (patches from Mauro)
Browse files Browse the repository at this point in the history
Merge media fixes from Mauro Carvalho Chehab:
 "This contains two patches fixing problems with my patch series meant
  to make USB drivers to work again after the DMA on stack changes.

  The last patch on this series is actually not related to DMA on stack.
  It solves a longstanding bug affecting module unload, causing
  module_put() to be called twice. It was reported by the user who
  reported and tested the issues with the gp8psk driver with the DMA
  fixup patches. As we're late at -rc cycle, maybe you prefer to not
  apply it right now. If this is the case, I'll add to the pile of
  patches for 4.10.

  Exceptionally this time, I'm sending the patches via e-mail, because
  I'm on another trip, and won't be able to use the usual procedure
  until Monday. Also, it is only three patches, and you followed already
  the discussions about the first one"

* emailed patches from Mauro Carvalho Chehab <mchehab@osg.samsung.com>:
  gp8psk: Fix DVB frontend attach
  gp8psk: fix gp8psk_usb_in_op() logic
  dvb-usb: move data_mutex to struct dvb_usb_device
  • Loading branch information
Linus Torvalds committed Nov 13, 2016
2 parents acb57b7 + 7a0786c commit e861d89
Show file tree
Hide file tree
Showing 14 changed files with 310 additions and 249 deletions.
5 changes: 5 additions & 0 deletions drivers/media/dvb-frontends/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,11 @@ config DVB_AS102_FE
depends on DVB_CORE
default DVB_AS102

config DVB_GP8PSK_FE
tristate
depends on DVB_CORE
default DVB_USB_GP8PSK

comment "DVB-C (cable) frontends"
depends on DVB_CORE

Expand Down
1 change: 1 addition & 0 deletions drivers/media/dvb-frontends/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
obj-$(CONFIG_DVB_AF9033) += af9033.o
obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o
obj-$(CONFIG_DVB_GP8PSK_FE) += gp8psk-fe.o
obj-$(CONFIG_DVB_TC90522) += tc90522.o
obj-$(CONFIG_DVB_HORUS3A) += horus3a.o
obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,27 @@
*
* see Documentation/dvb/README.dvb-usb for more information
*/
#include "gp8psk.h"

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include "gp8psk-fe.h"
#include "dvb_frontend.h"

static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");

#define dprintk(fmt, arg...) do { \
if (debug) \
printk(KERN_DEBUG pr_fmt("%s: " fmt), \
__func__, ##arg); \
} while (0)

struct gp8psk_fe_state {
struct dvb_frontend fe;
struct dvb_usb_device *d;
void *priv;
const struct gp8psk_fe_ops *ops;
bool is_rev1;
u8 lock;
u16 snr;
unsigned long next_status_check;
Expand All @@ -29,22 +45,24 @@ static int gp8psk_tuned_to_DCII(struct dvb_frontend *fe)
{
struct gp8psk_fe_state *st = fe->demodulator_priv;
u8 status;
gp8psk_usb_in_op(st->d, GET_8PSK_CONFIG, 0, 0, &status, 1);

st->ops->in(st->priv, GET_8PSK_CONFIG, 0, 0, &status, 1);
return status & bmDCtuned;
}

static int gp8psk_set_tuner_mode(struct dvb_frontend *fe, int mode)
{
struct gp8psk_fe_state *state = fe->demodulator_priv;
return gp8psk_usb_out_op(state->d, SET_8PSK_CONFIG, mode, 0, NULL, 0);
struct gp8psk_fe_state *st = fe->demodulator_priv;

return st->ops->out(st->priv, SET_8PSK_CONFIG, mode, 0, NULL, 0);
}

static int gp8psk_fe_update_status(struct gp8psk_fe_state *st)
{
u8 buf[6];
if (time_after(jiffies,st->next_status_check)) {
gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0,0,&st->lock,1);
gp8psk_usb_in_op(st->d, GET_SIGNAL_STRENGTH, 0,0,buf,6);
st->ops->in(st->priv, GET_SIGNAL_LOCK, 0, 0, &st->lock, 1);
st->ops->in(st->priv, GET_SIGNAL_STRENGTH, 0, 0, buf, 6);
st->snr = (buf[1]) << 8 | buf[0];
st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
}
Expand Down Expand Up @@ -116,13 +134,12 @@ static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front

static int gp8psk_fe_set_frontend(struct dvb_frontend *fe)
{
struct gp8psk_fe_state *state = fe->demodulator_priv;
struct gp8psk_fe_state *st = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u8 cmd[10];
u32 freq = c->frequency * 1000;
int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct);

deb_fe("%s()\n", __func__);
dprintk("%s()\n", __func__);

cmd[4] = freq & 0xff;
cmd[5] = (freq >> 8) & 0xff;
Expand All @@ -136,21 +153,21 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend *fe)
switch (c->delivery_system) {
case SYS_DVBS:
if (c->modulation != QPSK) {
deb_fe("%s: unsupported modulation selected (%d)\n",
dprintk("%s: unsupported modulation selected (%d)\n",
__func__, c->modulation);
return -EOPNOTSUPP;
}
c->fec_inner = FEC_AUTO;
break;
case SYS_DVBS2: /* kept for backwards compatibility */
deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
dprintk("%s: DVB-S2 delivery system selected\n", __func__);
break;
case SYS_TURBO:
deb_fe("%s: Turbo-FEC delivery system selected\n", __func__);
dprintk("%s: Turbo-FEC delivery system selected\n", __func__);
break;

default:
deb_fe("%s: unsupported delivery system selected (%d)\n",
dprintk("%s: unsupported delivery system selected (%d)\n",
__func__, c->delivery_system);
return -EOPNOTSUPP;
}
Expand All @@ -161,9 +178,9 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend *fe)
cmd[3] = (c->symbol_rate >> 24) & 0xff;
switch (c->modulation) {
case QPSK:
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
if (st->is_rev1)
if (gp8psk_tuned_to_DCII(fe))
gp8psk_bcm4500_reload(state->d);
st->ops->reload(st->priv);
switch (c->fec_inner) {
case FEC_1_2:
cmd[9] = 0; break;
Expand Down Expand Up @@ -207,18 +224,18 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend *fe)
cmd[9] = 0;
break;
default: /* Unknown modulation */
deb_fe("%s: unsupported modulation selected (%d)\n",
dprintk("%s: unsupported modulation selected (%d)\n",
__func__, c->modulation);
return -EOPNOTSUPP;
}

if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
if (st->is_rev1)
gp8psk_set_tuner_mode(fe, 0);
gp8psk_usb_out_op(state->d, TUNE_8PSK, 0, 0, cmd, 10);
st->ops->out(st->priv, TUNE_8PSK, 0, 0, cmd, 10);

state->lock = 0;
state->next_status_check = jiffies;
state->status_check_interval = 200;
st->lock = 0;
st->next_status_check = jiffies;
st->status_check_interval = 200;

return 0;
}
Expand All @@ -228,9 +245,9 @@ static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
{
struct gp8psk_fe_state *st = fe->demodulator_priv;

deb_fe("%s\n",__func__);
dprintk("%s\n", __func__);

if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
if (st->ops->out(st->priv, SEND_DISEQC_COMMAND, m->msg[0], 0,
m->msg, m->msg_len)) {
return -EINVAL;
}
Expand All @@ -243,12 +260,12 @@ static int gp8psk_fe_send_diseqc_burst(struct dvb_frontend *fe,
struct gp8psk_fe_state *st = fe->demodulator_priv;
u8 cmd;

deb_fe("%s\n",__func__);
dprintk("%s\n", __func__);

/* These commands are certainly wrong */
cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;

if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
if (st->ops->out(st->priv, SEND_DISEQC_COMMAND, cmd, 0,
&cmd, 0)) {
return -EINVAL;
}
Expand All @@ -258,10 +275,10 @@ static int gp8psk_fe_send_diseqc_burst(struct dvb_frontend *fe,
static int gp8psk_fe_set_tone(struct dvb_frontend *fe,
enum fe_sec_tone_mode tone)
{
struct gp8psk_fe_state* state = fe->demodulator_priv;
struct gp8psk_fe_state *st = fe->demodulator_priv;

if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
(tone == SEC_TONE_ON), 0, NULL, 0)) {
if (st->ops->out(st->priv, SET_22KHZ_TONE,
(tone == SEC_TONE_ON), 0, NULL, 0)) {
return -EINVAL;
}
return 0;
Expand All @@ -270,9 +287,9 @@ static int gp8psk_fe_set_tone(struct dvb_frontend *fe,
static int gp8psk_fe_set_voltage(struct dvb_frontend *fe,
enum fe_sec_voltage voltage)
{
struct gp8psk_fe_state* state = fe->demodulator_priv;
struct gp8psk_fe_state *st = fe->demodulator_priv;

if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
if (st->ops->out(st->priv, SET_LNB_VOLTAGE,
voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
return -EINVAL;
}
Expand All @@ -281,52 +298,60 @@ static int gp8psk_fe_set_voltage(struct dvb_frontend *fe,

static int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff)
{
struct gp8psk_fe_state* state = fe->demodulator_priv;
return gp8psk_usb_out_op(state->d, USE_EXTRA_VOLT, onoff, 0,NULL,0);
struct gp8psk_fe_state *st = fe->demodulator_priv;

return st->ops->out(st->priv, USE_EXTRA_VOLT, onoff, 0, NULL, 0);
}

static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
{
struct gp8psk_fe_state* state = fe->demodulator_priv;
struct gp8psk_fe_state *st = fe->demodulator_priv;
u8 cmd = sw_cmd & 0x7f;

if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
NULL, 0)) {
if (st->ops->out(st->priv, SET_DN_SWITCH, cmd, 0, NULL, 0))
return -EINVAL;
}
if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
0, NULL, 0)) {

if (st->ops->out(st->priv, SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
0, NULL, 0))
return -EINVAL;
}

return 0;
}

static void gp8psk_fe_release(struct dvb_frontend* fe)
{
struct gp8psk_fe_state *state = fe->demodulator_priv;
kfree(state);
struct gp8psk_fe_state *st = fe->demodulator_priv;

kfree(st);
}

static struct dvb_frontend_ops gp8psk_fe_ops;

struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
struct dvb_frontend *gp8psk_fe_attach(const struct gp8psk_fe_ops *ops,
void *priv, bool is_rev1)
{
struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
if (s == NULL)
goto error;

s->d = d;
memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
s->fe.demodulator_priv = s;

goto success;
error:
return NULL;
success:
return &s->fe;
}
struct gp8psk_fe_state *st;

if (!ops || !ops->in || !ops->out || !ops->reload) {
pr_err("Error! gp8psk-fe ops not defined.\n");
return NULL;
}

st = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
if (!st)
return NULL;

memcpy(&st->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
st->fe.demodulator_priv = st;
st->ops = ops;
st->priv = priv;
st->is_rev1 = is_rev1;

pr_info("Frontend %sattached\n", is_rev1 ? "revision 1 " : "");

return &st->fe;
}
EXPORT_SYMBOL_GPL(gp8psk_fe_attach);

static struct dvb_frontend_ops gp8psk_fe_ops = {
.delsys = { SYS_DVBS },
Expand Down
82 changes: 82 additions & 0 deletions drivers/media/dvb-frontends/gp8psk-fe.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* gp8psk_fe driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#ifndef GP8PSK_FE_H
#define GP8PSK_FE_H

#include <linux/types.h>

/* gp8psk commands */

#define GET_8PSK_CONFIG 0x80 /* in */
#define SET_8PSK_CONFIG 0x81
#define I2C_WRITE 0x83
#define I2C_READ 0x84
#define ARM_TRANSFER 0x85
#define TUNE_8PSK 0x86
#define GET_SIGNAL_STRENGTH 0x87 /* in */
#define LOAD_BCM4500 0x88
#define BOOT_8PSK 0x89 /* in */
#define START_INTERSIL 0x8A /* in */
#define SET_LNB_VOLTAGE 0x8B
#define SET_22KHZ_TONE 0x8C
#define SEND_DISEQC_COMMAND 0x8D
#define SET_DVB_MODE 0x8E
#define SET_DN_SWITCH 0x8F
#define GET_SIGNAL_LOCK 0x90 /* in */
#define GET_FW_VERS 0x92
#define GET_SERIAL_NUMBER 0x93 /* in */
#define USE_EXTRA_VOLT 0x94
#define GET_FPGA_VERS 0x95
#define CW3K_INIT 0x9d

/* PSK_configuration bits */
#define bm8pskStarted 0x01
#define bm8pskFW_Loaded 0x02
#define bmIntersilOn 0x04
#define bmDVBmode 0x08
#define bm22kHz 0x10
#define bmSEL18V 0x20
#define bmDCtuned 0x40
#define bmArmed 0x80

/* Satellite modulation modes */
#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */
#define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */
#define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */
#define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */

#define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */
#define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */
#define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */
#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
#define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */
#define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */

/* firmware revision id's */
#define GP8PSK_FW_REV1 0x020604
#define GP8PSK_FW_REV2 0x020704
#define GP8PSK_FW_VERS(_fw_vers) \
((_fw_vers)[2]<<0x10 | (_fw_vers)[1]<<0x08 | (_fw_vers)[0])

struct gp8psk_fe_ops {
int (*in)(void *priv, u8 req, u16 value, u16 index, u8 *b, int blen);
int (*out)(void *priv, u8 req, u16 value, u16 index, u8 *b, int blen);
int (*reload)(void *priv);
};

struct dvb_frontend *gp8psk_fe_attach(const struct gp8psk_fe_ops *ops,
void *priv, bool is_rev1);

#endif
2 changes: 1 addition & 1 deletion drivers/media/usb/dvb-usb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
dvb-usb-vp702x-objs := vp702x.o vp702x-fe.o
obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o

dvb-usb-gp8psk-objs := gp8psk.o gp8psk-fe.o
dvb-usb-gp8psk-objs := gp8psk.o
obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o

dvb-usb-dtt200u-objs := dtt200u.o dtt200u-fe.o
Expand Down
Loading

0 comments on commit e861d89

Please sign in to comment.