mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 13:27:06 +09:00
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:
committed by
Dongjin Kim
parent
a482792ed4
commit
c9d8cb176a
@@ -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");
|
||||
|
||||
@@ -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;\
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user