support new SDR modulator image with MCI

This commit is contained in:
rjkm 2020-12-01 15:58:35 +01:00
parent 65b3128cbe
commit 46a4f7476a
9 changed files with 302 additions and 123 deletions

View File

@ -2507,8 +2507,10 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr)
rm = io_regmap(input, 1); rm = io_regmap(input, 1);
input->regs = DDB_LINK_TAG(port->lnr) | input->regs = DDB_LINK_TAG(port->lnr) |
(rm->input->base + rm->input->size * nr); (rm->input->base + rm->input->size * nr);
#if 0
dev_info(dev->dev, "init link %u, input %u, regs %08x\n", dev_info(dev->dev, "init link %u, input %u, regs %08x\n",
port->lnr, nr, input->regs); port->lnr, nr, input->regs);
#endif
if (dev->has_dma) { if (dev->has_dma) {
const struct ddb_regmap *rm0 = io_regmap(input, 0); const struct ddb_regmap *rm0 = io_regmap(input, 0);
u32 base = rm0->irq_base_idma; u32 base = rm0->irq_base_idma;
@ -3210,6 +3212,12 @@ struct ddb_i2c_msg {
__u32 mlen; __u32 mlen;
}; };
struct ddb_mci_msg {
__u32 link;
struct mci_command cmd;
struct mci_result res;
};
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) #define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) #define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) #define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
@ -3222,6 +3230,7 @@ struct ddb_i2c_msg {
#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) #define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg) #define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg)
#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg) #define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg)
#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg)
#define DDB_NAME "ddbridge" #define DDB_NAME "ddbridge"
@ -3433,6 +3442,24 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EIO; return -EIO;
break; break;
} }
case IOCTL_DDB_MCI_CMD:
{
struct ddb_mci_msg msg;
struct ddb_link *link;
int res;
if (copy_from_user(&msg, parg, sizeof(msg)))
return -EFAULT;
if (msg.link > 3)
return -EFAULT;
link = &dev->link[msg.link];
if (!link->mci_base)
return -EFAULT;
res = ddb_mci_cmd_link(link, &msg.cmd, &msg.res);
if (copy_to_user(parg, &msg, sizeof(msg)))
return -EFAULT;
return res;
}
default: default:
return -ENOTTY; return -ENOTTY;
} }
@ -4414,6 +4441,13 @@ static int ddb_init_boards(struct ddb *dev)
usleep_range(2000, 3000); usleep_range(2000, 3000);
} }
ddb_init_tempmon(link); ddb_init_tempmon(link);
if (info->regmap->mci) {
if (link->info->type == DDB_OCTOPUS_MCI ||
((link->info->type == DDB_MOD) &&
(link->ids.regmapid & 0xfff0)))
mci_init(link);
}
} }
return 0; return 0;
} }

View File

@ -124,6 +124,32 @@ static const struct ddb_regset octopus_i2c_buf = {
/****************************************************************************/ /****************************************************************************/
static const struct ddb_regset max_mci = {
.base = 0x500,
.num = 0x01,
.size = 0x04,
};
static const struct ddb_regset max_mci_buf = {
.base = 0x600,
.num = 0x01,
.size = 0x100,
};
static const struct ddb_regset sdr_mci = {
.base = 0x260,
.num = 0x01,
.size = 0x04,
};
static const struct ddb_regset sdr_mci_buf = {
.base = 0x300,
.num = 0x01,
.size = 0x100,
};
/****************************************************************************/
static const struct ddb_regset octopro_input = { static const struct ddb_regset octopro_input = {
.base = 0x400, .base = 0x400,
.num = 0x14, .num = 0x14,
@ -224,6 +250,25 @@ static const struct ddb_regmap octopus_map = {
.output = &octopus_output, .output = &octopus_output,
}; };
static const struct ddb_regmap octopus_mci_map = {
.irq_version = 1,
.irq_base_i2c = 0,
.irq_base_idma = 8,
.irq_base_odma = 16,
.irq_base_mci = 0,
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.idma = &octopus_idma,
.idma_buf = &octopus_idma_buf,
.odma = &octopus_odma,
.odma_buf = &octopus_odma_buf,
.input = &octopus_input,
.output = &octopus_output,
.mci = &max_mci,
.mci_buf = &max_mci_buf,
};
static const struct ddb_regmap octopro_map = { static const struct ddb_regmap octopro_map = {
.irq_version = 2, .irq_version = 2,
.irq_base_i2c = 32, .irq_base_i2c = 32,
@ -280,10 +325,14 @@ static const struct ddb_regmap octopus_sdr_map = {
.irq_version = 2, .irq_version = 2,
.irq_base_odma = 64, .irq_base_odma = 64,
.irq_base_rate = 32, .irq_base_rate = 32,
.irq_base_mci = 10,
.output = &octopus_sdr_output, .output = &octopus_sdr_output,
.odma = &octopus_mod_2_odma, .odma = &octopus_mod_2_odma,
.odma_buf = &octopus_mod_2_odma_buf, .odma_buf = &octopus_mod_2_odma_buf,
.channel = &octopus_mod_2_channel, .channel = &octopus_mod_2_channel,
.mci = &sdr_mci,
.mci_buf = &sdr_mci_buf,
}; };
static const struct ddb_regmap gtl_mini = { static const struct ddb_regmap gtl_mini = {
@ -537,6 +586,16 @@ static const struct ddb_info ddb_sdr_iq = {
.tempmon_irq = 8, .tempmon_irq = 8,
}; };
static const struct ddb_info ddb_sdr_iq2 = {
.type = DDB_MOD,
.name = "Digital Devices SDR IQ2",
.version = 17,
.regmap = &octopus_sdr_map,
.port_num = 4,
.temp_num = 1,
.tempmon_irq = 8,
};
static const struct ddb_info ddb_sdr_dvbt = { static const struct ddb_info ddb_sdr_dvbt = {
.type = DDB_MOD, .type = DDB_MOD,
.name = "Digital Devices DVBT", .name = "Digital Devices DVBT",
@ -568,7 +627,7 @@ static const struct ddb_info ddb_octopro = {
static const struct ddb_info ddb_s2_48 = { static const struct ddb_info ddb_s2_48 = {
.type = DDB_OCTOPUS_MAX, .type = DDB_OCTOPUS_MAX,
.name = "Digital Devices MAX S8 4/8", .name = "Digital Devices MAX S8 4/8",
.regmap = &octopus_map, .regmap = &octopus_mci_map,
.port_num = 4, .port_num = 4,
.i2c_mask = 0x01, .i2c_mask = 0x01,
.board_control = 1, .board_control = 1,
@ -635,10 +694,12 @@ static const struct ddb_info ddb_c2t2i_8 = {
.tempmon_irq = 24, .tempmon_irq = 24,
}; };
/****************************************************************************/
static const struct ddb_info ddb_s2x_48 = { static const struct ddb_info ddb_s2x_48 = {
.type = DDB_OCTOPUS_MCI, .type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX SX8", .name = "Digital Devices MAX SX8",
.regmap = &octopus_map, .regmap = &octopus_mci_map,
.port_num = 4, .port_num = 4,
.i2c_mask = 0x00, .i2c_mask = 0x00,
.tempmon_irq = 24, .tempmon_irq = 24,
@ -650,7 +711,7 @@ static const struct ddb_info ddb_s2x_48 = {
static const struct ddb_info ddb_s2x_48_b = { static const struct ddb_info ddb_s2x_48_b = {
.type = DDB_OCTOPUS_MCI, .type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX SX8 Basic", .name = "Digital Devices MAX SX8 Basic",
.regmap = &octopus_map, .regmap = &octopus_mci_map,
.port_num = 4, .port_num = 4,
.i2c_mask = 0x00, .i2c_mask = 0x00,
.tempmon_irq = 24, .tempmon_irq = 24,
@ -662,7 +723,7 @@ static const struct ddb_info ddb_s2x_48_b = {
static const struct ddb_info ddb_m4 = { static const struct ddb_info ddb_m4 = {
.type = DDB_OCTOPUS_MCI, .type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX M4", .name = "Digital Devices MAX M4",
.regmap = &octopus_map, .regmap = &octopus_mci_map,
.port_num = 2, .port_num = 2,
.i2c_mask = 0x00, .i2c_mask = 0x00,
.tempmon_irq = 24, .tempmon_irq = 24,
@ -671,6 +732,8 @@ static const struct ddb_info ddb_m4 = {
.temp_num = 1, .temp_num = 1,
}; };
/****************************************************************************/
static const struct ddb_info ddb_gtl_mini = { static const struct ddb_info ddb_gtl_mini = {
.type = DDB_OCTOPUS, .type = DDB_OCTOPUS,
.name = "Digital Devices Octopus GT Mini", .name = "Digital Devices Octopus GT Mini",
@ -813,6 +876,8 @@ static const struct ddb_device_id ddb_device_ids[] = {
DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv), DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv),
DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq), DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq),
DDB_DEVID(0x0222, 0x0001, ddb_sdr_dvbt), DDB_DEVID(0x0222, 0x0001, ddb_sdr_dvbt),
DDB_DEVID(0x0223, 0x0001, ddb_sdr_iq2),
DDB_DEVID(0xffff, 0xffff, ddb_sdr_iq2),
/* testing on OctopusNet Pro */ /* testing on OctopusNet Pro */
DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin), DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin),

View File

@ -427,6 +427,7 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
DDB_DEVICE_ANY(0x0220), DDB_DEVICE_ANY(0x0220),
DDB_DEVICE_ANY(0x0221), DDB_DEVICE_ANY(0x0221),
DDB_DEVICE_ANY(0x0222), DDB_DEVICE_ANY(0x0222),
DDB_DEVICE_ANY(0x0223),
DDB_DEVICE_ANY(0x0320), DDB_DEVICE_ANY(0x0320),
DDB_DEVICE_ANY(0x0321), DDB_DEVICE_ANY(0x0321),
DDB_DEVICE_ANY(0x0322), DDB_DEVICE_ANY(0x0322),

View File

@ -28,151 +28,178 @@
static LIST_HEAD(mci_list); static LIST_HEAD(mci_list);
static int mci_reset(struct mci *state) static int mci_reset(struct ddb_link *link)
{ {
struct ddb_link *link = state->base->link; const struct ddb_regmap *regmap = link->info->regmap;
u32 control;
u32 status = 0; u32 status = 0;
u32 timeout = 40; u32 timeout = 40;
ddblwritel(link, MCI_CONTROL_RESET, MCI_CONTROL); if (!regmap || ! regmap->mci)
ddblwritel(link, 0, MCI_CONTROL + 4); /* 1= no internal init */ return -EINVAL;
msleep(300); control = regmap->mci->base;
ddblwritel(link, 0, MCI_CONTROL);
if ((link->info->type == DDB_OCTOPUS_MCI) &&
(ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) {
ddblwritel(link, MCI_CONTROL_RESET, control);
ddblwritel(link, 0, control + 4); /* 1= no internal init */
msleep(300);
}
ddblwritel(link, 0, control);
while (1) { while (1) {
status = ddblreadl(link, MCI_CONTROL); status = ddblreadl(link, control);
if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY) if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY)
break; break;
if (--timeout == 0) if (--timeout == 0)
break; break;
msleep(50); msleep(50);
} }
if ((status & MCI_CONTROL_READY) == 0) dev_info(link->dev->dev, "MCI control port @ %08x\n", control);
if ((status & MCI_CONTROL_READY) == 0) {
dev_err(link->dev->dev, "MCI init failed!\n");
return -1; return -1;
if (link->ids.device == 0x0009 || link->ids.device == 0x000b) }
ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG); dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40-timeout)*50);
return 0; return 0;
} }
int ddb_mci_config(struct mci *state, u32 config) static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link,
{
struct ddb_link *link = state->base->link;
if (link->ids.device != 0x0009 && link->ids.device != 0x000b)
return -EINVAL;
ddblwritel(link, config, SX8_TSCONFIG);
return 0;
}
static int ddb_mci_cmd_raw_unlocked(struct mci *state,
u32 *cmd, u32 cmd_len, u32 *cmd, u32 cmd_len,
u32 *res, u32 res_len) u32 *res, u32 res_len)
{ {
struct ddb_link *link = state->base->link; const struct ddb_regmap *regmap = link->info->regmap;
u32 control, command, result;
u32 i, val; u32 i, val;
unsigned long stat; unsigned long stat;
val = ddblreadl(link, MCI_CONTROL); if (!regmap || ! regmap->mci)
return -EINVAL;
control = regmap->mci->base;
command = regmap->mci_buf->base;
result = command + MCI_COMMAND_SIZE;
val = ddblreadl(link, control);
if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND)) if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND))
return -EIO; return -EIO;
if (cmd && cmd_len) if (cmd && cmd_len)
for (i = 0; i < cmd_len; i++) for (i = 0; i < cmd_len; i++)
ddblwritel(link, cmd[i], MCI_COMMAND + i * 4); ddblwritel(link, cmd[i], command + i * 4);
val |= (MCI_CONTROL_START_COMMAND | MCI_CONTROL_ENABLE_DONE_INTERRUPT); val |= (MCI_CONTROL_START_COMMAND |
ddblwritel(link, val, MCI_CONTROL); MCI_CONTROL_ENABLE_DONE_INTERRUPT);
ddblwritel(link, val, control);
stat = wait_for_completion_timeout(&state->base->completion, HZ); stat = wait_for_completion_timeout(&link->mci_completion, HZ);
if (stat == 0) { if (stat == 0) {
u32 istat = ddblreadl(link, INTERRUPT_STATUS); u32 istat = ddblreadl(link, INTERRUPT_STATUS);
dev_err(state->base->link->dev->dev, "MCI timeout\n"); dev_err(link->dev->dev, "MCI timeout\n");
val = ddblreadl(link, MCI_CONTROL); val = ddblreadl(link, control);
if (val == 0xffffffff) { if (val == 0xffffffff) {
dev_err(state->base->link->dev->dev, dev_err(link->dev->dev,
"Lost PCIe link!\n"); "Lost PCIe link!\n");
return -EIO; return -EIO;
} else { } else {
dev_err(state->base->link->dev->dev, dev_err(link->dev->dev,
"DDBridge IRS %08x link %u\n", istat, link->nr); "DDBridge IRS %08x link %u\n",
istat, link->nr);
if (istat & 1) if (istat & 1)
ddblwritel(link, istat, INTERRUPT_ACK); ddblwritel(link, istat, INTERRUPT_ACK);
if (link->nr) if (link->nr)
ddbwritel(link->dev, 0xffffff, INTERRUPT_ACK); ddbwritel(link->dev,
0xffffff, INTERRUPT_ACK);
} }
} }
if (res && res_len) if (res && res_len)
for (i = 0; i < res_len; i++) for (i = 0; i < res_len; i++)
res[i] = ddblreadl(link, MCI_RESULT + i * 4); res[i] = ddblreadl(link, result + i * 4);
return 0; return 0;
} }
int ddb_mci_cmd_unlocked(struct mci *state, int ddb_mci_cmd_link(struct ddb_link *link,
struct mci_command *command, struct mci_command *command,
struct mci_result *result) struct mci_result *result)
{ {
u32 *cmd = (u32 *) command;
u32 *res = (u32 *) result;
return ddb_mci_cmd_raw_unlocked(state, cmd, sizeof(*command)/sizeof(u32),
res, sizeof(*result)/sizeof(u32));
}
int ddb_mci_cmd(struct mci *state,
struct mci_command *command,
struct mci_result *result)
{
int stat;
struct mci_result res; struct mci_result res;
int stat;
if (!result) if (!result)
result = &res; result = &res;
mutex_lock(&state->base->mci_lock); mutex_lock(&link->mci_lock);
stat = ddb_mci_cmd_raw_unlocked(state, stat = ddb_mci_cmd_raw_unlocked(link,
(u32 *)command, sizeof(*command)/sizeof(u32), (u32 *)command,
(u32 *)result, sizeof(*result)/sizeof(u32)); sizeof(*command)/sizeof(u32),
mutex_unlock(&state->base->mci_lock); (u32 *)result,
sizeof(*result)/sizeof(u32));
mutex_unlock(&link->mci_lock);
if (command && result && (result->status & 0x80)) if (command && result && (result->status & 0x80))
dev_warn(state->base->link->dev->dev, dev_warn(link->dev->dev,
"mci_command 0x%02x, error=0x%02x\n", "mci_command 0x%02x, error=0x%02x\n",
command->command, result->status); command->command, result->status);
return stat; return stat;
} }
static void mci_handler(void *priv)
{
struct ddb_link *link = (struct ddb_link *) priv;
complete(&link->mci_completion);
}
int mci_init(struct ddb_link *link)
{
int result;
mutex_init(&link->mci_lock);
init_completion(&link->mci_completion);
result = mci_reset(link);
if (result < 0)
return result;
if (link->ids.device == 0x0009 || link->ids.device == 0x000b)
ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG);
ddb_irq_set(link->dev, link->nr,
link->info->regmap->irq_base_mci,
mci_handler, link);
link->mci_ok = 1;
return result;
}
int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val)
{
struct mci_result result;
struct mci_command command = {
.command_word = cmd,
.params = { val },
};
return ddb_mci_cmd_link(link, &command, &result);
}
/****************************************************************************/
/****************************************************************************/
int ddb_mci_cmd(struct mci *state,
struct mci_command *command,
struct mci_result *result)
{
return ddb_mci_cmd_link(state->base->link, command, result);
}
int ddb_mci_cmd_raw(struct mci *state, int ddb_mci_cmd_raw(struct mci *state,
struct mci_command *command, u32 command_len, struct mci_command *command, u32 command_len,
struct mci_result *result, u32 result_len) struct mci_result *result, u32 result_len)
{ {
struct ddb_link *link = state->base->link;
int stat; int stat;
mutex_lock(&state->base->mci_lock); mutex_lock(&link->mci_lock);
stat = ddb_mci_cmd_raw_unlocked(state, stat = ddb_mci_cmd_raw_unlocked(link,
(u32 *)command, command_len, (u32 *)command, command_len,
(u32 *)result, result_len); (u32 *)result, result_len);
mutex_unlock(&state->base->mci_lock); mutex_unlock(&link->mci_lock);
return stat; return stat;
} }
#if 0
static int ddb_mci_get_iq(struct mci *mci, u32 demod, s16 *i, s16 *q)
{
int stat;
struct mci_command cmd;
struct mci_result res;
memset(&cmd, 0, sizeof(cmd));
memset(&res, 0, sizeof(res));
cmd.command = MCI_CMD_GET_IQSYMBOL;
cmd.demod = demod;
stat = ddb_mci_cmd(mci, &cmd, &res);
if (!stat) {
*i = res.iq_symbol.i;
*q = res.iq_symbol.q;
}
return stat;
}
#endif
int ddb_mci_get_status(struct mci *mci, struct mci_result *res) int ddb_mci_get_status(struct mci *mci, struct mci_result *res)
{ {
struct mci_command cmd; struct mci_command cmd;
@ -189,7 +216,8 @@ int ddb_mci_get_snr(struct dvb_frontend *fe)
p->cnr.len = 1; p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL; p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].svalue = (s64) mci->signal_info.dvbs2_signal_info.signal_to_noise * 10; p->cnr.stat[0].svalue =
(s64) mci->signal_info.dvbs2_signal_info.signal_to_noise * 10;
return 0; return 0;
} }
@ -306,6 +334,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
case SYS_ISDBT: case SYS_ISDBT:
break; break;
} }
/* post is correct, we cannot provide both pre and post at the same time */
/* set pre and post the same for now */
p->pre_bit_error.len = 1; p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue = p->pre_bit_error.stat[0].uvalue =
@ -316,6 +346,16 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
p->pre_bit_count.stat[0].uvalue = p->pre_bit_count.stat[0].uvalue =
mci->signal_info.dvbs2_signal_info.ber_denominator; mci->signal_info.dvbs2_signal_info.ber_denominator;
p->post_bit_error.len = 1;
p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->post_bit_error.stat[0].uvalue =
mci->signal_info.dvbs2_signal_info.ber_numerator;
p->post_bit_count.len = 1;
p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->post_bit_count.stat[0].uvalue =
mci->signal_info.dvbs2_signal_info.ber_denominator;
p->block_error.len = 1; p->block_error.len = 1;
p->block_error.stat[0].scale = FE_SCALE_COUNTER; p->block_error.stat[0].scale = FE_SCALE_COUNTER;
p->block_error.stat[0].uvalue = p->block_error.stat[0].uvalue =
@ -329,17 +369,10 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
p->strength.len = 1; p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL; p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].svalue = p->strength.stat[0].svalue = (s64)
mci->signal_info.dvbs2_signal_info.channel_power * 10; mci->signal_info.dvbs2_signal_info.channel_power * 10;
} }
static void mci_handler(void *priv)
{
struct mci_base *base = (struct mci_base *)priv;
complete(&base->completion);
}
static struct mci_base *match_base(void *key) static struct mci_base *match_base(void *key)
{ {
struct mci_base *p; struct mci_base *p;
@ -350,13 +383,8 @@ static struct mci_base *match_base(void *key)
return NULL; return NULL;
} }
static int probe(struct mci *state) struct dvb_frontend *ddb_mci_attach(struct ddb_input *input,
{ struct mci_cfg *cfg, int nr, int tuner)
mci_reset(state);
return 0;
}
struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int tuner)
{ {
struct ddb_port *port = input->port; struct ddb_port *port = input->port;
struct ddb *dev = port->dev; struct ddb *dev = port->dev;
@ -380,12 +408,11 @@ struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg
base->key = key; base->key = key;
base->count = 1; base->count = 1;
base->link = link; base->link = link;
mutex_init(&base->mci_lock); link->mci_base = base;
mutex_init(&base->tuner_lock); mutex_init(&base->tuner_lock);
ddb_irq_set(dev, link->nr, 0, mci_handler, base);
init_completion(&base->completion);
state->base = base; state->base = base;
if (probe(state) < 0) {
if (!link->mci_ok) {
kfree(base); kfree(base);
goto fail; goto fail;
} }

View File

@ -39,11 +39,6 @@
#define MIC_INTERFACE_OUT (0x0680) #define MIC_INTERFACE_OUT (0x0680)
#define MIC_INTERFACE_VER (0x06F0) #define MIC_INTERFACE_VER (0x06F0)
#define MCI_CONTROL (0x500)
#define MCI_COMMAND (0x600)
#define MCI_RESULT (0x680)
#define MCI_COMMAND_SIZE (0x80) #define MCI_COMMAND_SIZE (0x80)
#define MCI_RESULT_SIZE (0x80) #define MCI_RESULT_SIZE (0x80)
@ -686,7 +681,7 @@ struct mci_result {
} ISDBS_TMCCInfo; } ISDBS_TMCCInfo;
}; };
u32 version[3]; u32 version[3];
u32 version_rsvd; u8 version_rsvd;
u8 version_major; u8 version_major;
u8 version_minor; u8 version_minor;
u8 version_sub; u8 version_sub;
@ -767,9 +762,9 @@ struct mci_base {
struct list_head mci_list; struct list_head mci_list;
void *key; void *key;
struct ddb_link *link; struct ddb_link *link;
struct completion completion; // struct completion completion;
struct mutex tuner_lock; struct mutex tuner_lock;
struct mutex mci_lock; // struct mutex mci_lock;
int count; int count;
int type; int type;
}; };
@ -795,14 +790,14 @@ struct mci_cfg {
}; };
int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result); int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result);
int ddb_mci_cmd_raw(struct mci *state, struct mci_command *command, u32 command_len, int ddb_mci_cmd_link(struct ddb_link *link, struct mci_command *command, struct mci_result *result);
struct mci_result *result, u32 result_len);
int ddb_mci_config(struct mci *state, u32 config);
int ddb_mci_get_status(struct mci *mci, struct mci_result *res); int ddb_mci_get_status(struct mci *mci, struct mci_result *res);
int ddb_mci_get_snr(struct dvb_frontend *fe); int ddb_mci_get_snr(struct dvb_frontend *fe);
int ddb_mci_get_info(struct mci *mci); int ddb_mci_get_info(struct mci *mci);
int ddb_mci_get_strength(struct dvb_frontend *fe); int ddb_mci_get_strength(struct dvb_frontend *fe);
void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p); void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p);
int mci_init(struct ddb_link *link);
int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val);
extern struct mci_cfg ddb_max_sx8_cfg; extern struct mci_cfg ddb_max_sx8_cfg;
extern struct mci_cfg ddb_max_m4_cfg; extern struct mci_cfg ddb_max_m4_cfg;

View File

@ -644,6 +644,7 @@ static int mod_set_sdr_attenuator(struct ddb *dev, u32 value)
static int mod_set_sdr_gain(struct ddb *dev, u32 gain) static int mod_set_sdr_gain(struct ddb *dev, u32 gain)
{ {
u32 control = ddbreadl(dev, SDR_CONTROL); u32 control = ddbreadl(dev, SDR_CONTROL);
struct ddb_link *link = &dev->link[0];
if (control & 0x01000000) { if (control & 0x01000000) {
if (gain > 511) if (gain > 511)
@ -658,6 +659,8 @@ static int mod_set_sdr_gain(struct ddb *dev, u32 gain)
return -EINVAL; return -EINVAL;
ddbwritel(dev, gain, SDR_GAIN_F); ddbwritel(dev, gain, SDR_GAIN_F);
} }
if (link->mci_ok)
mci_cmd_val(link, 0xc1, gain);
return 0; return 0;
} }
@ -1516,6 +1519,7 @@ static int mod3_set_ari(struct ddb_mod *mod, u32 rate)
static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate) static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate)
{ {
struct ddb *dev = mod->port->dev;
u32 cic, inc, bypass = 0; u32 cic, inc, bypass = 0;
switch (rate) { switch (rate) {
@ -1556,19 +1560,52 @@ static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate)
inc = 0x7684BD82; //1988410754; inc = 0x7684BD82; //1988410754;
cic = 7; cic = 7;
break; break;
case SYS_DVBS2_22: case SYS_DVB_22:
inc = 0x72955555; // 1922389333; inc = 0x72955555; // 1922389333;
cic = 5; cic = 5;
bypass = 2; bypass = 2;
break; break;
case SYS_DVBS2_24: case SYS_DVB_24:
inc = 0x7d000000; inc = 0x7d000000;
cic = 5; cic = 5;
bypass = 2; bypass = 2;
break; break;
case SYS_DVB_30:
inc = 0x7d000000;
cic = 4;
bypass = 2;
break;
case SYS_ISDBS_2886:
inc = 0x78400000;
cic = 4;
bypass = 2;
break;
default: default:
{
u64 a;
if (rate < 1000000)
return -EINVAL; return -EINVAL;
if (rate > 30720000)
return -EINVAL;
bypass = 2;
if (rate > 24576000)
cic = 4;
else if (rate > 20480000)
cic = 5;
else if (rate > 17554286)
cic = 6;
else if (rate > 15360000)
cic = 7;
else
cic = 8;
a = (1ULL << 31) * rate * 2 * cic;
inc = div_s64(a, 245760000);
break;
} }
}
dev_info(dev->dev, "inc = %08x, cic = %u, bypass = %u\n", inc, cic, bypass);
ddbwritel(mod->port->dev, inc, SDR_CHANNEL_ARICW(mod->port->nr)); ddbwritel(mod->port->dev, inc, SDR_CHANNEL_ARICW(mod->port->nr));
ddbwritel(mod->port->dev, (cic << 8) | (bypass << 4), ddbwritel(mod->port->dev, (cic << 8) | (bypass << 4),
SDR_CHANNEL_CONFIG(mod->port->nr)); SDR_CHANNEL_CONFIG(mod->port->nr));
@ -1596,6 +1633,7 @@ static int mod3_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
case MODULATOR_GAIN: case MODULATOR_GAIN:
return mod_set_sdr_gain(mod->port->dev, tvp->u.data); return mod_set_sdr_gain(mod->port->dev, tvp->u.data);
} }
return -EINVAL; return -EINVAL;
} }

View File

@ -114,6 +114,16 @@ static void release(struct dvb_frontend *fe)
kfree(state); kfree(state);
} }
static int ddb_mci_tsconfig(struct mci *state, u32 config)
{
struct ddb_link *link = state->base->link;
if (link->ids.device != 0x0009 && link->ids.device != 0x000b)
return -EINVAL;
ddblwritel(link, config, SX8_TSCONFIG);
return 0;
}
static int read_status(struct dvb_frontend *fe, enum fe_status *status) static int read_status(struct dvb_frontend *fe, enum fe_status *status)
{ {
int stat; int stat;
@ -172,7 +182,7 @@ static int stop_iq(struct dvb_frontend *fe)
cmd.command = SX8_CMD_STOP_IQ; cmd.command = SX8_CMD_STOP_IQ;
cmd.demod = state->mci.demod; cmd.demod = state->mci.demod;
ddb_mci_cmd(&state->mci, &cmd, NULL); ddb_mci_cmd(&state->mci, &cmd, NULL);
ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL); ddb_mci_tsconfig(&state->mci, SX8_TSCONFIG_MODE_NORMAL);
mutex_lock(&mci_base->tuner_lock); mutex_lock(&mci_base->tuner_lock);
sx8_base->tuner_use_count[input]--; sx8_base->tuner_use_count[input]--;
@ -209,7 +219,7 @@ static int stop(struct dvb_frontend *fe)
cmd.demod = state->mci.demod; cmd.demod = state->mci.demod;
cmd.output = 0; cmd.output = 0;
ddb_mci_cmd(&state->mci, &cmd, NULL); ddb_mci_cmd(&state->mci, &cmd, NULL);
ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL); ddb_mci_tsconfig(&state->mci, SX8_TSCONFIG_MODE_NORMAL);
} }
} }
mutex_lock(&mci_base->tuner_lock); mutex_lock(&mci_base->tuner_lock);
@ -331,7 +341,7 @@ unlock:
cmd.demod = state->mci.demod; cmd.demod = state->mci.demod;
cmd.output = p->stream_id & 7; cmd.output = p->stream_id & 7;
ddb_mci_cmd(&state->mci, &cmd, NULL); ddb_mci_cmd(&state->mci, &cmd, NULL);
ddb_mci_config(&state->mci, ts_config); ddb_mci_tsconfig(&state->mci, ts_config);
} }
if (p->stream_id != NO_STREAM_ID_FILTER && !(p->stream_id & 0xf0000000)) if (p->stream_id != NO_STREAM_ID_FILTER && !(p->stream_id & 0xf0000000))
flags |= 0x80; flags |= 0x80;
@ -411,7 +421,7 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
stat = ddb_mci_cmd(&state->mci, &cmd, NULL); stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
if (stat) if (stat)
stop_iq(fe); stop_iq(fe);
ddb_mci_config(&state->mci, ts_config); ddb_mci_tsconfig(&state->mci, ts_config);
return stat; return stat;
} }

View File

@ -114,6 +114,7 @@ struct ddb_regmap {
u32 irq_base_odma; u32 irq_base_odma;
u32 irq_base_gtl; u32 irq_base_gtl;
u32 irq_base_rate; u32 irq_base_rate;
u32 irq_base_mci;
const struct ddb_regset *i2c; const struct ddb_regset *i2c;
const struct ddb_regset *i2c_buf; const struct ddb_regset *i2c_buf;
@ -127,6 +128,9 @@ struct ddb_regmap {
const struct ddb_regset *channel; const struct ddb_regset *channel;
const struct ddb_regset *gtl; const struct ddb_regset *gtl;
const struct ddb_regset *mci;
const struct ddb_regset *mci_buf;
}; };
struct ddb_ids { struct ddb_ids {
@ -427,6 +431,9 @@ struct ddb_link {
struct ddb_irq irq[256]; struct ddb_irq irq[256];
struct mci_base *mci_base; struct mci_base *mci_base;
struct completion mci_completion;
struct mutex mci_lock;
int mci_ok;
}; };
struct ddb { struct ddb {

View File

@ -44,8 +44,10 @@ enum mod_output_rate {
SYS_ISDBT_6 = 16, SYS_ISDBT_6 = 16,
SYS_J83B_64_6 = 24, SYS_J83B_64_6 = 24,
SYS_J83B_256_6 = 25, SYS_J83B_256_6 = 25,
SYS_DVBS2_22 = 32, SYS_DVB_22 = 32,
SYS_DVBS2_24 = 33, SYS_DVB_24 = 33,
SYS_DVB_30 = 34,
SYS_ISDBS_2886 = 48,
}; };