Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e861d890 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'media-fixes' (patches from Mauro)

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
parents acb57b75 7a0786c1
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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

+1 −0
Original line number Diff line number Diff line
@@ -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
+82 −57
Original line number Diff line number Diff line
@@ -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;
@@ -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;
	}
@@ -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;
@@ -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;
	}
@@ -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;
@@ -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;
}
@@ -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;
	}
@@ -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;
	}
@@ -258,9 +275,9 @@ 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,
	if (st->ops->out(st->priv, SET_22KHZ_TONE,
			 (tone == SEC_TONE_ON), 0, NULL, 0)) {
		return -EINVAL;
	}
@@ -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;
	}
@@ -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;
	struct gp8psk_fe_state *st;

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

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

	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 },
+82 −0
Original line number Diff line number Diff line
/*
 * 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
+1 −1
Original line number Diff line number Diff line
@@ -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
Loading