dvb: dsc: added DES support [1/1]

PD#SWPL-5358

Problem:
no DES decrypt code for dvb descrambler

Solution:
added DES mode to dvb descrambler driver

Verify:
Local build on R314

Change-Id: Ie534e1f50428af1ea4eed1c720257dc93be9bd96
Signed-off-by: Zhiqiang Han <zhiqiang.han@amlogic.com>
This commit is contained in:
Zhiqiang Han
2019-03-01 20:56:17 +08:00
committed by Dongjin Kim
parent a482792ed4
commit c9d8cb176a
3 changed files with 290 additions and 264 deletions

View File

@@ -309,13 +309,12 @@ static inline int _set(int v, int b) { return b; }
static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags,
enum ca_cw_type type, u8 *key);
static int dsc_set_aes_key(struct aml_dsc_channel *ch, int flags,
static int dsc_set_aes_des_key(struct aml_dsc_channel *ch, int flags,
enum ca_cw_type type, u8 *key);
static void aml_ci_plus_disable_output(void);
static void aml_ci_plus_disable(void);
static void am_ci_plus_set_output(struct aml_dsc_channel *ch);
static void aml_ci_plus_enable(void);
static void dmxn_op_chan(int dmx, int ch, int(*op)(int, int), int ch_op)
{
@@ -1757,43 +1756,97 @@ int dsc_set_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type,
/*struct aml_dsc *dsc = ch->dsc;*/
int ret = -1;
if (type == CA_CW_DVB_CSA_EVEN || type == CA_CW_DVB_CSA_ODD) {
switch (type) {
case CA_CW_DVB_CSA_EVEN:
case CA_CW_DVB_CSA_ODD:
aml_ci_plus_disable();
ret = dsc_set_csa_key(ch, flags, type, key);
if (ret != 0)
goto END;
/* Different with old mode, do change */
if (ch->work_mode == CIPLUS_MODE || ch->work_mode == -1) {
if (ch->work_mode == -1)
pr_error("Dsc set output and enable\n");
pr_inf("dsc[%d:%d] enable\n",
ch->dsc->id, ch->id);
else
pr_error("Dsc set output change from ciplus\n");
aml_ci_plus_disable_output();
pr_inf("dsc[%d:%d] enable (from ciplus)\n",
ch->dsc->id, ch->id);
ch->aes_mode = AES_ECB_MODE;
/*aml_ci_plus_disable();*/
ch->work_mode = DVBCSA_MODE;
}
} else if (type == CA_CW_AES_EVEN ||
type == CA_CW_AES_ODD ||
type == CA_CW_AES_EVEN_IV ||
type == CA_CW_AES_ODD_IV) {
ret = dsc_set_aes_key(ch, flags, type, key);
break;
case CA_CW_AES_EVEN:
case CA_CW_AES_ODD:
case CA_CW_AES_EVEN_IV:
case CA_CW_AES_ODD_IV:
case CA_CW_DES_EVEN:
case CA_CW_DES_ODD:
am_ci_plus_set_output(ch);
ret = dsc_set_aes_des_key(ch, flags, type, key);
if (ret != 0)
goto END;
/* Different with old mode, do change */
if (ch->work_mode == DVBCSA_MODE || ch->work_mode == -1) {
if (ch->work_mode == -1)
pr_error("Ciplus set output and enable\n");
pr_inf("dsc[%d:%d] ciplus enable\n",
ch->dsc->id, ch->id);
else
pr_error("Ciplus set output change from dsc\n");
am_ci_plus_set_output(ch);
aml_ci_plus_enable();
pr_inf("dsc[%d:%d] ciplus enable (from dsc)\n",
ch->dsc->id, ch->id);
ch->work_mode = CIPLUS_MODE;
}
break;
default:
break;
}
END:
return ret;
}
int dsc_set_keys(struct aml_dsc_channel *ch)
{
int types = ch->set & 0xFFFFFF;
int flag = (ch->set >> 24) & 0xFF;
int i;
u8 *k;
int ret = 0;
for (i = 0; i < CA_CW_TYPE_MAX; i++) {
if (types & (1 << i)) {
k = NULL;
switch (i) {
case CA_CW_DVB_CSA_EVEN:
case CA_CW_AES_EVEN:
case CA_CW_DES_EVEN:
k = ch->even;
break;
case CA_CW_DVB_CSA_ODD:
case CA_CW_AES_ODD:
case CA_CW_DES_ODD:
k = ch->odd;
break;
case CA_CW_AES_EVEN_IV:
k = ch->even_iv;
break;
case CA_CW_AES_ODD_IV:
k = ch->odd_iv;
break;
default:
break;
}
/*
if (k)
pr_inf("dsc ch:%d flag:%d type:%d\n", ch->id, flag, i);
*/
if (k)
ret = dsc_set_key(ch, flag,
i,
k);
}
}
return 0;
}
static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags,
enum ca_cw_type type, u8 *key)
{
@@ -1801,18 +1854,10 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags,
int is_dsc2 = (dsc->id == 1) ? 1 : 0;
u16 k0, k1, k2, k3;
u32 key0, key1;
int reg; /*not sure if reg readable*/
/* u32 data;
* u32 pid = 0x1fff;
*/
int from_kl = flags & CA_CW_FROM_KL;
/* int pid = ch->pid; */
int reg;
if (from_kl) {
if (flags & DSC_FROM_KL) {
k0 = k1 = k2 = k3 = 0;
/* ch->used = 1;
* dsc_set_pid(ch, pid);
*/
/*dummy write to check if kl not working*/
key0 = key1 = 0;
WRITE_MPEG_REG(COMM_DESC_KEY0, key0);
@@ -1847,9 +1892,9 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags,
key1 = (k2 << 16) | k3;
WRITE_MPEG_REG(COMM_DESC_KEY0, key0);
WRITE_MPEG_REG(COMM_DESC_KEY1, key1);
WRITE_MPEG_REG(COMM_DESC_KEY_RW,
(ch->id + type * DSC_COUNT)+(is_dsc2 ? 16 : 0));
reg = (ch->id + type * DSC_COUNT)+(is_dsc2 ? 16 : 0);
WRITE_MPEG_REG(COMM_DESC_KEY_RW, reg);
}
return 0;
@@ -1874,6 +1919,8 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags,
#define KEY_WR_AES_IV_A 4
#define KEY_WR_AES_B 3
#define KEY_WR_AES_A 2
#define KEY_WR_DES_B 1
#define KEY_WR_DES_A 0
#define CNTL_ENABLE 3
#define AES_CBC_DISABLE 2
@@ -1883,6 +1930,9 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags,
#define AES_MSG_OUT_ENDIAN 24
#define AES_MSG_IN_ENDIAN 20
#define AES_KEY_ENDIAN 16
#define DES_MSG_OUT_ENDIAN 8
#define DES_MSG_IN_ENDIAN 4
#define DES_KEY_ENDIAN 0
#if 0
@@ -1955,22 +2005,28 @@ void aml_ci_plus_set_iv(struct aml_dsc_channel *ch, enum ca_cw_type type,
* 0 for ebc
* 1 for cbc
*/
static void aml_ci_plus_config(int key_endian, int aes_mode)
static void aml_ci_plus_config(int key_endian, int mode, int aes_not_des)
{
unsigned int data;
WRITE_MPEG_REG(CIPLUS_ENDIAN, (15 << AES_MSG_OUT_ENDIAN) |
(15 << AES_MSG_IN_ENDIAN) |
(key_endian << AES_KEY_ENDIAN));
int dis_aes_cbc =
(aes_not_des && (mode == AES_ECB_MODE)) ? 1 : 0;
WRITE_MPEG_REG(CIPLUS_ENDIAN,
(15 << AES_MSG_OUT_ENDIAN)
| (15 << AES_MSG_IN_ENDIAN)
| (key_endian << AES_KEY_ENDIAN)
|
(15 << DES_MSG_OUT_ENDIAN)
| (15 << DES_MSG_IN_ENDIAN)
| (key_endian << DES_KEY_ENDIAN)
);
data = READ_MPEG_REG(CIPLUS_ENDIAN);
WRITE_MPEG_REG(CIPLUS_CONFIG, (1 << CNTL_ENABLE) |
(aes_mode << AES_CBC_DISABLE) |
/*1 << AES_CBC_DISABLE : ECB
*0 << AES_CBC_DISABLE : CBC
*/
(1 << AES_EN));
WRITE_MPEG_REG(CIPLUS_CONFIG,
(1 << CNTL_ENABLE)
| (dis_aes_cbc << AES_CBC_DISABLE)
| (((aes_not_des) ? 1 : 0) << AES_EN)
| (((aes_not_des) ? 0 : 1) << DES_EN)
);
data = READ_MPEG_REG(DEMUX_CONTROL);
}
/*
@@ -1980,42 +2036,69 @@ static void am_ci_plus_set_output(struct aml_dsc_channel *ch)
{
struct aml_dsc *dsc = ch->dsc;
u32 data;
u32 in = 0, out = 0;
int set = 0;
if (dsc->id != 0) {
pr_error("Ciplus set output can only work at dsc0 device\n");
return;
}
switch (dsc->source) {
case AM_TS_SRC_DMX0:
in = 0;
break;
case AM_TS_SRC_DMX1:
in = 1;
break;
case AM_TS_SRC_DMX2:
in = 2;
break;
default:
break;
}
if (ciplus_out_auto_mode == 1) {
data = READ_MPEG_REG(STB_TOP_CONFIG);
switch (dsc->source) {
switch (dsc->dst) {
case AM_TS_SRC_DMX0:
data |= 1 << CIPLUS_OUT_SEL;
ciplus_out_sel = 1;
break;
out = 1;
break;
case AM_TS_SRC_DMX1:
data |= 2 << CIPLUS_OUT_SEL;
ciplus_out_sel = 2;
break;
out = 2;
break;
case AM_TS_SRC_DMX2:
data |= 4 << CIPLUS_OUT_SEL;
ciplus_out_sel = 4;
break;
out = 4;
break;
default:
pr_error("ciplus auto set source failed\n");
return;
break;
}
WRITE_MPEG_REG(STB_TOP_CONFIG, data);
set = 1;
ciplus_out_sel = out;
} else if (ciplus_out_sel >= 0 && ciplus_out_sel <= 7) {
pr_error("Set output selection %d\n", ciplus_out_sel);
set = 1;
out = ciplus_out_sel;
} else {
pr_error("dsc ciplus out config is invalid\n");
}
if (set) {
/* Set ciplus input source ,
* output set 0 means no output. ---> need confirm.
* if output set 0 still affects dsc output, we need to disable
* ciplus module.
*/
data = READ_MPEG_REG(STB_TOP_CONFIG);
data &= ~(3<<CIPLUS_IN_SEL);
data |= in << CIPLUS_IN_SEL;
data &= ~(7<<CIPLUS_OUT_SEL);
WRITE_MPEG_REG(STB_TOP_CONFIG, data |
(ciplus_out_sel << CIPLUS_OUT_SEL));
} else
pr_error("Ciplus out config is invalid\n");
data |= out << CIPLUS_OUT_SEL;
WRITE_MPEG_REG(STB_TOP_CONFIG, data);
pr_inf("dsc ciplus in[%x] out[%x] %s\n", in, out,
(ciplus_out_auto_mode) ? "" : "force");
}
}
#if 0
/*
* Ciplus output has high priority,
* disable it's output will let dsc output go.
@@ -2035,8 +2118,11 @@ static void aml_ci_plus_enable(void)
data = READ_MPEG_REG(STB_TOP_CONFIG);
WRITE_MPEG_REG(CIPLUS_CONFIG,
(1 << CNTL_ENABLE) | (1 << AES_EN));
(1 << CNTL_ENABLE)
| (1 << AES_EN)
| (1 << DES_EN));
}
#endif
static void aml_ci_plus_disable(void)
{
@@ -2047,94 +2133,104 @@ static void aml_ci_plus_disable(void)
data = READ_MPEG_REG(STB_TOP_CONFIG);
WRITE_MPEG_REG(STB_TOP_CONFIG, data &
~((1 << CIPLUS_IN_SEL) | (7 << CIPLUS_OUT_SEL)));
/* WRITE_MPEG_REG(CIPLUS_CONFIG,
* (0 << CNTL_ENABLE) | (0 << AES_EN));
*/
}
static int dsc_set_aes_key(struct aml_dsc_channel *ch, int flags,
static int dsc_set_aes_des_key(struct aml_dsc_channel *ch, int flags,
enum ca_cw_type type, u8 *key)
{
unsigned int k0, k1, k2, k3, index_flag = 0;
unsigned int k0, k1, k2, k3;
int iv = 0, aes = 0, des = 0;
int ab_iv = 0, ab_aes = 0, ab_des = 0;
int from_kl = flags & CA_CW_FROM_KL;
int aes_a = 0, aes_b = 0;
/* Set odd/even */
if (type == CA_CW_AES_EVEN) {
aes_a = 0;
aes_b = 1;
if (!from_kl) {
k3 = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3];
k2 = (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7];
k1 = (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11];
k0 = (key[12] << 24) | (key[13] << 16)
| (key[14] << 8) | key[15];
} else
k0 = k1 = k2 = k3 = 0;
switch (type) {
case CA_CW_AES_EVEN:
ab_aes = (from_kl) ? 0x2 : 0x1;
if (ch->aes_mode == -1)
ch->aes_mode = AES_ECB_MODE;
} else if (type == CA_CW_AES_ODD) {
aes_a = 1;
aes_b = 0;
aes = 1;
break;
case CA_CW_AES_ODD:
ab_aes = (from_kl) ? 0x1 : 0x2;
if (ch->aes_mode == -1)
ch->aes_mode = AES_ECB_MODE;
} else if ((type == CA_CW_AES_EVEN_IV)
|| (type == CA_CW_AES_ODD_IV)) {
aml_ci_plus_set_iv(ch, type, key);
aes = 1;
break;
case CA_CW_AES_EVEN_IV:
ab_iv = 0x1;
ch->aes_mode = AES_CBC_MODE;
return 0;
iv = 1;
break;
case CA_CW_AES_ODD_IV:
ab_iv = 0x2;
ch->aes_mode = AES_CBC_MODE;
iv = 1;
break;
case CA_CW_DES_EVEN:
ab_des = 0x1;
ch->aes_mode = AES_ECB_MODE;
des = 1;
break;
case CA_CW_DES_ODD:
ab_des = 0x2;
ch->aes_mode = AES_ECB_MODE;
des = 1;
break;
default:
break;
}
/* Set endian and cbc/ecb mode */
if (from_kl)
aml_ci_plus_config(7, ch->aes_mode);
aml_ci_plus_config(7, ch->aes_mode, (aes && !des));
else
aml_ci_plus_config(0, ch->aes_mode);
aml_ci_plus_config(0, ch->aes_mode, (aes && !des));
/* Write keys to work */
if (from_kl) {
k0 = k1 = k2 = k3 = 0;
/* dummy write to
* check if kl not working
*/
if (iv || aes) {
WRITE_MPEG_REG(CIPLUS_KEY0, k0);
WRITE_MPEG_REG(CIPLUS_KEY1, k1);
WRITE_MPEG_REG(CIPLUS_KEY2, k2);
WRITE_MPEG_REG(CIPLUS_KEY3, k3);
WRITE_MPEG_REG(CIPLUS_KEY_WR,
(ch->id << 9) |
/* bit[11:9] the key of index,
* need match PID index
*/
(0 << 8) | /* bit[8] des key use cw[127:64]*/
(0 << 7) | /* bit[7] aes iv use cw*/
(1 << 6) | /* bit[6] aes/des key use cw*/
(0 << 5) | /* bit[5] write AES IV B value*/
(0 << 4) | /* bit[4] write AES IV A value*/
(aes_b << 3) | /* bit[3] write AES B key*/
(aes_a << 2) | /* bit[2] write AES A key*/
(0 << 1) | /* bit[1] write DES B key*/
(0)); /* bit[0] write DES A key*/
} else {
k3 = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3];
k2 = (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7];
k1 = (key[8] << 24) | (key[9] << 16) |
(key[10] << 8) | key[11];
k0 = (key[12] << 24) | (key[13] << 16) |
(key[14] << 8) | key[15];
WRITE_MPEG_REG(CIPLUS_KEY0, k0);
WRITE_MPEG_REG(CIPLUS_KEY1, k1);
WRITE_MPEG_REG(CIPLUS_KEY2, k2);
WRITE_MPEG_REG(CIPLUS_KEY3, k3);
index_flag = (ch->id << 9);
if (type == 2) { /* even */
WRITE_MPEG_REG(CIPLUS_KEY_WR,
index_flag | (1<<KEY_WR_AES_A));
} else if (type == 3) { /* odd */
WRITE_MPEG_REG(CIPLUS_KEY_WR,
index_flag | (1<<KEY_WR_AES_B));
}
} else {/*des*/
WRITE_MPEG_REG(CIPLUS_KEY0, k2);
WRITE_MPEG_REG(CIPLUS_KEY1, k3);
WRITE_MPEG_REG(CIPLUS_KEY2, 0);
WRITE_MPEG_REG(CIPLUS_KEY3, 0);
}
WRITE_MPEG_REG(CIPLUS_KEY_WR,
(ch->id << 9) |
/* bit[11:9] the key of index,
need match PID index*/
((from_kl && des) ? (1 << 8) : 0) |
/* bit[8] des key use cw[127:64]*/
(0 << 7) | /* bit[7] aes iv use cw*/
((from_kl && (aes || des)) ? (1 << 6) : 0) |
/* bit[6] aes/des key use cw*/
/* bit[5] write AES IV B value*/
(ab_iv << 4) | /* bit[4] write AES IV A value*/
/* bit[3] write AES B key*/
(ab_aes << 2) | /* bit[2] write AES A key*/
/* bit[1] write DES B key*/
(ab_des)); /* bit[0] write DES A key*/
/*
pr_inf("k:%08x:%08x:%08x:%08x kl:%d aes:%d des:%d ab_iv:%d ab_aes:%d ab_des:%d id:%d mod:%d\n",
k0, k1, k2, k3,
from_kl, aes, des, ab_iv, ab_aes, ab_des, ch->id, ch->aes_mode);
*/
return 0;
}
void dsc_release(void)
{
aml_ci_plus_disable();
@@ -2150,7 +2246,7 @@ int dsc_enable(struct aml_dsc *dsc, int enable)
(1 << ENABLE_DES_PL)|
(1 << ENABLE_DES_PL_CLK)));
} else if (dsc->id == 1) {
WRITE_MPEG_REG(COMM_DESC_2_CTL, 0);
WRITE_MPEG_REG(COMM_DESC_2_CTL, 0);
}
return 0;
}
@@ -3600,28 +3696,9 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq)
/*if(ch->used) */
{
ch->id = n;
ch->work_mode = -1;
dsc_set_pid(ch, ch->pid);
if (ch->flags & DSC_SET_EVEN) {
dsc_set_key(ch, 0,
CA_CW_DVB_CSA_EVEN,
ch->even);
}
if (ch->flags & DSC_SET_ODD) {
dsc_set_key(ch, 0,
CA_CW_DVB_CSA_ODD,
ch->odd);
}
if (ch->flags & DSC_SET_AES_EVEN) {
dsc_set_key(ch, 0,
CA_CW_AES_EVEN,
ch->aes_even);
}
if (ch->flags & DSC_SET_AES_ODD) {
dsc_set_key(ch, 0,
CA_CW_AES_ODD,
ch->aes_odd);
}
dsc_set_keys(ch);
}
}
}
@@ -3803,28 +3880,9 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx,
for (n = 0; n < DSC_COUNT; n++) {
struct aml_dsc_channel *ch = &dsc->channel[n];
/*if(ch->used) */
ch->work_mode = -1;
dsc_set_pid(ch, ch->pid);
if (ch->flags & DSC_SET_EVEN) {
dsc_set_key(ch, 0,
CA_CW_DVB_CSA_EVEN,
ch->even);
}
if (ch->flags & DSC_SET_ODD) {
dsc_set_key(ch, 0,
CA_CW_DVB_CSA_ODD,
ch->odd);
}
if (ch->flags & DSC_SET_AES_EVEN) {
dsc_set_key(ch, 0,
CA_CW_AES_EVEN,
ch->aes_even);
}
if (ch->flags & DSC_SET_AES_ODD) {
dsc_set_key(ch, 0,
CA_CW_AES_ODD,
ch->aes_odd);
}
dsc_set_keys(ch);
}
}
}
@@ -4827,34 +4885,34 @@ int aml_dsc_hw_set_source(struct aml_dsc *dsc,
}
if (src_reset) {
pr_dbg("dsc%d source changed: %d -> %d\n",
pr_inf("dsc%d source changed: %d -> %d\n",
dsc->id, org_src, hw_src);
if (org_src != -1) {
pr_dbg("reset dmx%d\n", (org_src - AM_TS_SRC_DMX0));
pr_inf("reset dmx%d\n", (org_src - AM_TS_SRC_DMX0));
dmx_reset_dmx_id_hw_ex_unlock(dvb,
(org_src - AM_TS_SRC_DMX0), 0);
}
if (hw_src != -1) {
pr_dbg("reset dmx%d\n", (hw_src - AM_TS_SRC_DMX0));
pr_inf("reset dmx%d\n", (hw_src - AM_TS_SRC_DMX0));
dmx_reset_dmx_id_hw_ex_unlock(dvb,
(hw_src - AM_TS_SRC_DMX0), 0);
} else
dsc_enable(dsc, 0);
}
if (dst_reset) {
pr_dbg("dsc%d dest changed: %d -> %d\n",
pr_inf("dsc%d dest changed: %d -> %d\n",
dsc->id, org_dst, hw_dst);
if (((!src_reset) && (org_dst != -1)) ||
(src_reset && (org_dst != -1) &&
(org_dst != org_src) && (org_dst != hw_src))) {
pr_dbg("reset dmx%d\n", (org_dst - AM_TS_SRC_DMX0));
pr_inf("reset dmx%d\n", (org_dst - AM_TS_SRC_DMX0));
dmx_reset_dmx_id_hw_ex_unlock(dvb,
(org_dst - AM_TS_SRC_DMX0), 0);
}
if (((!src_reset) && (hw_dst != -1)) ||
(src_reset && (hw_dst != -1)
&& (hw_dst != org_src) && (hw_dst != hw_src))) {
pr_dbg("reset dmx%d\n", (hw_dst - AM_TS_SRC_DMX0));
pr_inf("reset dmx%d\n", (hw_dst - AM_TS_SRC_DMX0));
dmx_reset_dmx_id_hw_ex_unlock(dvb,
(hw_dst - AM_TS_SRC_DMX0), 0);
}
@@ -4867,47 +4925,6 @@ int aml_dsc_hw_set_source(struct aml_dsc *dsc,
return ret;
}
int aml_ciplus_hw_set_source(int src)
{
int hw_src = 0;
int hw_dst = 0;
u32 data;
switch (src) {
case DMX_SOURCE_FRONT0_OFFSET:
hw_src = 0;
hw_dst = 1;
break;
case DMX_SOURCE_FRONT1_OFFSET:
hw_src = 1;
hw_dst = 2;
break;
case DMX_SOURCE_FRONT2_OFFSET:
hw_src = 2;
hw_dst = 4;
break;
default:
return -1;
}
data = READ_MPEG_REG(STB_TOP_CONFIG);
/* Set ciplus input source ,
* output set 0 means no output. ---> need confirm.
* if output set 0 still affects dsc output, we need to disable
* ciplus module.
*/
data &= ~(3<<CIPLUS_IN_SEL);
WRITE_MPEG_REG(STB_TOP_CONFIG, data |
(hw_src << CIPLUS_IN_SEL));
data &= ~(7<<CIPLUS_OUT_SEL);
WRITE_MPEG_REG(STB_TOP_CONFIG, data |
(hw_dst << CIPLUS_OUT_SEL));
aml_ci_plus_enable();
return 0;
}
int aml_tso_hw_set_source(struct aml_dvb *dvb, dmx_source_t src)
{
int ret = 0;
@@ -5238,22 +5255,29 @@ static ssize_t ciplus_output_ctrl_show(struct class *class,
char *buf)
{
int ret;
char *out = "none";
pr_error("output demux use 3 bit to indicate. ");
pr_error("1bit:demux0 2bit:demux1 3bit:demux2\n");
if (ciplus_out_auto_mode == 1)
ret = sprintf(buf, "Using auto mode, value: %x\n",
ciplus_out_sel);
else
ret = sprintf(buf, "%d\n", ciplus_out_sel);
pr_error("ciplus output path:\n");
if (ciplus_out_sel&1)
pr_error("demux0 ");
if (ciplus_out_sel&1<<1)
pr_error("demux1 ");
if (ciplus_out_sel&1<<2)
pr_error("demux2 ");
pr_error("\n");
pr_inf("output demux use 3 bit to indicate.\n");
pr_inf("1bit:demux0 2bit:demux1 3bit:demux2\n");
switch (ciplus_out_sel) {
case 1:
out = "dmx0";
break;
case 2:
out = "dmx1";
break;
case 4:
out = "dmx2";
break;
default:
break;
}
ret = sprintf(buf, "%s 0x%x %s\n",
out,
ciplus_out_sel,
(ciplus_out_auto_mode) ? "" : "(force)");
return ret;
}
@@ -5263,9 +5287,6 @@ static ssize_t ciplus_output_ctrl_store(struct class *class,
{
int i, tmp;
pr_error("output demux use 3 bit to indicate. ");
pr_error("1bit:demux0 2bit:demux1 3bit:demux2, 8 for auto\n");
/*i = sscanf(buf, "%d", &tmp); */
i = kstrtoint(buf, -1, &tmp);
if (tmp > 8 || tmp < 0)
pr_error("Invalid output set\n");

View File

@@ -341,7 +341,7 @@ static void dsc_channel_alloc(struct aml_dsc *dsc, int id, unsigned int pid)
ch->work_mode = -1;
ch->id = id;
ch->pid = pid;
ch->flags = 0;
ch->set = 0;
ch->dsc = dsc;
ch->aes_mode = -1;
@@ -358,7 +358,7 @@ static void dsc_channel_free(struct aml_dsc_channel *ch)
dsc_release();
ch->pid = 0x1fff;
ch->flags = 0;
ch->set = 0;
ch->work_mode = -1;
ch->aes_mode = -1;
}
@@ -373,15 +373,22 @@ static void dsc_reset(struct aml_dsc *dsc)
static int get_dsc_key_work_mode(enum ca_cw_type cw_type)
{
int work_mode = 0;
int work_mode = DVBCSA_MODE;
if (cw_type == CA_CW_DVB_CSA_EVEN || cw_type == CA_CW_DVB_CSA_ODD)
switch (cw_type) {
case CA_CW_DVB_CSA_EVEN:
case CA_CW_DVB_CSA_ODD:
work_mode = DVBCSA_MODE;
else if (cw_type == CA_CW_AES_EVEN ||
cw_type == CA_CW_AES_ODD ||
cw_type == CA_CW_AES_EVEN_IV ||
cw_type == CA_CW_AES_ODD_IV) {
break;
case CA_CW_AES_EVEN:
case CA_CW_AES_ODD:
case CA_CW_AES_ODD_IV:
case CA_CW_AES_EVEN_IV:
case CA_CW_DES_EVEN:
case CA_CW_DES_ODD:
work_mode = CIPLUS_MODE;
default:
break;
}
return work_mode;
}
@@ -409,6 +416,8 @@ static void dsc_ciplus_switch_check(struct aml_dsc_channel *ch,
pr_error("Dsc work mode changed,");
pr_error("but there are still some channels");
pr_error("run in different mode\n");
pr_error("mod_pre[%d] -> mod[%d] ch[%d]\n",
pch->work_mode, work_mode, i);
}
}
}
@@ -424,32 +433,28 @@ static int dsc_set_cw(struct aml_dsc *dsc, struct ca_descr_ex *d)
switch (d->type) {
case CA_CW_DVB_CSA_EVEN:
memcpy(ch->even, d->cw, 8);
ch->flags &= ~(DSC_SET_AES_EVEN|DSC_SET_AES_ODD);
ch->flags |= DSC_SET_EVEN;
case CA_CW_AES_EVEN:
case CA_CW_DES_EVEN:
memcpy(ch->even, d->cw, DSC_KEY_SIZE_MAX);
break;
case CA_CW_DVB_CSA_ODD:
memcpy(ch->odd, d->cw, 8);
ch->flags &= ~(DSC_SET_AES_EVEN|DSC_SET_AES_ODD);
ch->flags |= DSC_SET_ODD;
break;
case CA_CW_AES_EVEN:
memcpy(ch->aes_even, d->cw, 16);
ch->flags &= ~(DSC_SET_EVEN|DSC_SET_ODD);
ch->flags |= DSC_SET_AES_EVEN;
break;
case CA_CW_AES_ODD:
memcpy(ch->aes_odd, d->cw, 16);
ch->flags &= ~(DSC_SET_EVEN|DSC_SET_ODD);
ch->flags |= DSC_SET_AES_ODD;
case CA_CW_DES_ODD:
memcpy(ch->odd, d->cw, DSC_KEY_SIZE_MAX);
break;
case CA_CW_AES_EVEN_IV:
memcpy(ch->even_iv, d->cw, DSC_KEY_SIZE_MAX);
break;
case CA_CW_AES_ODD_IV:
memcpy(ch->odd_iv, d->cw, DSC_KEY_SIZE_MAX);
break;
default:
break;
}
if (d->flags & CA_CW_FROM_KL)
ch->flags = DSC_FROM_KL;
ch->set |= (1 << d->type) | (d->flags << 24);
/*do key set*/
dsc_set_key(ch, d->flags, d->type, d->cw);
dsc_ciplus_switch_check(ch, d->type);
@@ -714,7 +719,7 @@ static int aml_dvb_dsc_init(struct aml_dvb *advb,
for (i = 0; i < DSC_COUNT; i++) {
dsc->channel[i].id = i;
dsc->channel[i].used = 0;
dsc->channel[i].flags = 0;
dsc->channel[i].set = 0;
dsc->channel[i].pid = 0x1fff;
dsc->channel[i].dsc = dsc;
}
@@ -890,8 +895,6 @@ static ssize_t dsc##i##_store_source(struct class *class, \
else \
dst = src; \
aml_dsc_hw_set_source(&aml_dvb_device.dsc[i], src, dst);\
if (i == 0) \
aml_ciplus_hw_set_source(src); \
return size;\
}

View File

@@ -133,14 +133,16 @@ struct aml_filter {
#define DSC_SET_AES_ODD 8
#define DSC_FROM_KL 16
#define DSC_KEY_SIZE_MAX 16
struct aml_dsc_channel {
int pid;
u8 even[8];
u8 odd[8];
u8 aes_even[16];
u8 aes_odd[16];
u8 even[DSC_KEY_SIZE_MAX];
u8 odd[DSC_KEY_SIZE_MAX];
u8 even_iv[DSC_KEY_SIZE_MAX];
u8 odd_iv[DSC_KEY_SIZE_MAX];
int used;
int flags;
int set;
int id;
struct aml_dsc *dsc;
int work_mode;