ps3av_cmd.c

来自「linux 内核源代码」· C语言 代码 · 共 935 行 · 第 1/2 页

C
935
字号
	res = get_status(&av_audio_mute);	if (res)		printk(KERN_ERR "PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res);	return res;}static const struct {	u32 fs;	u8 mclk;} ps3av_cnv_mclk_table[] = {	{ PS3AV_CMD_AUDIO_FS_44K, PS3AV_CMD_AV_MCLK_512 },	{ PS3AV_CMD_AUDIO_FS_48K, PS3AV_CMD_AV_MCLK_512 },	{ PS3AV_CMD_AUDIO_FS_88K, PS3AV_CMD_AV_MCLK_256 },	{ PS3AV_CMD_AUDIO_FS_96K, PS3AV_CMD_AV_MCLK_256 },	{ PS3AV_CMD_AUDIO_FS_176K, PS3AV_CMD_AV_MCLK_128 },	{ PS3AV_CMD_AUDIO_FS_192K, PS3AV_CMD_AV_MCLK_128 }};static u8 ps3av_cnv_mclk(u32 fs){	unsigned int i;	for (i = 0; i < ARRAY_SIZE(ps3av_cnv_mclk_table); i++)		if (ps3av_cnv_mclk_table[i].fs == fs)			return ps3av_cnv_mclk_table[i].mclk;	printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs);	return 0;}#define BASE	PS3AV_CMD_AUDIO_FS_44Kstatic const u32 ps3av_ns_table[][5] = {					/*   D1,    D2,    D3,    D4,    D5 */	[PS3AV_CMD_AUDIO_FS_44K-BASE] =	{  6272,  6272, 17836, 17836,  8918 },	[PS3AV_CMD_AUDIO_FS_48K-BASE] =	{  6144,  6144, 11648, 11648,  5824 },	[PS3AV_CMD_AUDIO_FS_88K-BASE] =	{ 12544, 12544, 35672, 35672, 17836 },	[PS3AV_CMD_AUDIO_FS_96K-BASE] =	{ 12288, 12288, 23296, 23296, 11648 },	[PS3AV_CMD_AUDIO_FS_176K-BASE] =	{ 25088, 25088, 71344, 71344, 35672 },	[PS3AV_CMD_AUDIO_FS_192K-BASE] =	{ 24576, 24576, 46592, 46592, 23296 }};static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid){	u32 av_vid, ns_val;	int d;	d = ns_val = 0;	av_vid = ps3av_vid_video2av(video_vid);	switch (av_vid) {	case PS3AV_CMD_AV_VID_480I:	case PS3AV_CMD_AV_VID_576I:		d = 0;		break;	case PS3AV_CMD_AV_VID_480P:	case PS3AV_CMD_AV_VID_576P:		d = 1;		break;	case PS3AV_CMD_AV_VID_1080I_60HZ:	case PS3AV_CMD_AV_VID_1080I_50HZ:		d = 2;		break;	case PS3AV_CMD_AV_VID_720P_60HZ:	case PS3AV_CMD_AV_VID_720P_50HZ:		d = 3;		break;	case PS3AV_CMD_AV_VID_1080P_60HZ:	case PS3AV_CMD_AV_VID_1080P_50HZ:	case PS3AV_CMD_AV_VID_WXGA:	case PS3AV_CMD_AV_VID_SXGA:	case PS3AV_CMD_AV_VID_WUXGA:		d = 4;		break;	default:		printk(KERN_ERR "%s failed, vid:%x\n", __func__, video_vid);		break;	}	if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K)		printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs);	else		ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d];	*ns++ = ns_val & 0x000000FF;	*ns++ = (ns_val & 0x0000FF00) >> 8;	*ns = (ns_val & 0x00FF0000) >> 16;}#undef BASEstatic u8 ps3av_cnv_enable(u32 source, const u8 *enable){	u8 ret = 0;	if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) {		ret = 0x03;	} else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) {		ret = ((enable[0] << 4) + (enable[1] << 5) + (enable[2] << 6) +		       (enable[3] << 7)) | 0x01;	} else		printk(KERN_ERR "%s failed, source:%x\n", __func__, source);	return ret;}static u8 ps3av_cnv_fifomap(const u8 *map){	u8 ret = 0;	ret = map[0] + (map[1] << 2) + (map[2] << 4) + (map[3] << 6);	return ret;}static u8 ps3av_cnv_inputlen(u32 word_bits){	u8 ret = 0;	switch (word_bits) {	case PS3AV_CMD_AUDIO_WORD_BITS_16:		ret = PS3AV_CMD_AV_INPUTLEN_16;		break;	case PS3AV_CMD_AUDIO_WORD_BITS_20:		ret = PS3AV_CMD_AV_INPUTLEN_20;		break;	case PS3AV_CMD_AUDIO_WORD_BITS_24:		ret = PS3AV_CMD_AV_INPUTLEN_24;		break;	default:		printk(KERN_ERR "%s failed, word_bits:%x\n", __func__,		       word_bits);		break;	}	return ret;}static u8 ps3av_cnv_layout(u32 num_of_ch){	if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) {		printk(KERN_ERR "%s failed, num_of_ch:%x\n", __func__,		       num_of_ch);		return 0;	}	return num_of_ch == PS3AV_CMD_AUDIO_NUM_OF_CH_2 ? 0x0 : 0x1;}static void ps3av_cnv_info(struct ps3av_audio_info_frame *info,			   const struct ps3av_pkt_audio_mode *mode){	info->pb1.cc = mode->audio_num_of_ch + 1;	/* CH2:0x01 --- CH8:0x07 */	info->pb1.ct = 0;	info->pb2.sf = 0;	info->pb2.ss = 0;	info->pb3 = 0;		/* check mode->audio_format ?? */	info->pb4 = mode->audio_layout;	info->pb5.dm = mode->audio_downmix;	info->pb5.lsv = mode->audio_downmix_level;}static void ps3av_cnv_chstat(u8 *chstat, const u8 *cs_info){	memcpy(chstat, cs_info, 5);}u32 ps3av_cmd_set_av_audio_param(void *p, u32 port,				 const struct ps3av_pkt_audio_mode *audio_mode,				 u32 video_vid){	struct ps3av_pkt_av_audio_param *param;	param = (struct ps3av_pkt_av_audio_param *)p;	memset(param, 0, sizeof(*param));	ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM, sizeof(*param),		      &param->send_hdr);	param->avport = port;	param->mclk = ps3av_cnv_mclk(audio_mode->audio_fs) | 0x80;	ps3av_cnv_ns(param->ns, audio_mode->audio_fs, video_vid);	param->enable = ps3av_cnv_enable(audio_mode->audio_source,					 audio_mode->audio_enable);	param->swaplr = 0x09;	param->fifomap = ps3av_cnv_fifomap(audio_mode->audio_map);	param->inputctrl = 0x49;	param->inputlen = ps3av_cnv_inputlen(audio_mode->audio_word_bits);	param->layout = ps3av_cnv_layout(audio_mode->audio_num_of_ch);	ps3av_cnv_info(&param->info, audio_mode);	ps3av_cnv_chstat(param->chstat, audio_mode->audio_cs_info);	return sizeof(*param);}/* default cs val */static const u8 ps3av_mode_cs_info[] = {	0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00};#define CS_44	0x00#define CS_48	0x02#define CS_88	0x08#define CS_96	0x0a#define CS_176	0x0c#define CS_192	0x0e#define CS_MASK	0x0f#define CS_BIT	0x40void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,			      u32 ch, u32 fs, u32 word_bits, u32 format,			      u32 source){	int spdif_through, spdif_bitstream;	int i;	if (!(ch | fs | format | word_bits | source)) {		ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2;		fs = PS3AV_CMD_AUDIO_FS_48K;		word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;		format = PS3AV_CMD_AUDIO_FORMAT_PCM;		source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;	}	spdif_through = spdif_bitstream = 0;	/* XXX not supported */	/* audio mode */	memset(audio, 0, sizeof(*audio));	ps3av_set_hdr(PS3AV_CID_AUDIO_MODE, sizeof(*audio), &audio->send_hdr);	audio->avport = (u8) avport;	audio->mask = 0x0FFF;	/* XXX set all */	audio->audio_num_of_ch = ch;	audio->audio_fs = fs;	audio->audio_word_bits = word_bits;	audio->audio_format = format;	audio->audio_source = source;	switch (ch) {	case PS3AV_CMD_AUDIO_NUM_OF_CH_8:		audio->audio_enable[3] = 1;		/* fall through */	case PS3AV_CMD_AUDIO_NUM_OF_CH_6:		audio->audio_enable[2] = 1;		audio->audio_enable[1] = 1;		/* fall through */	case PS3AV_CMD_AUDIO_NUM_OF_CH_2:	default:		audio->audio_enable[0] = 1;	}	/* audio swap L/R */	for (i = 0; i < 4; i++)		audio->audio_swap[i] = PS3AV_CMD_AUDIO_SWAP_0;	/* no swap */	/* audio serial input mapping */	audio->audio_map[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0;	audio->audio_map[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1;	audio->audio_map[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2;	audio->audio_map[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3;	/* audio speaker layout */	if (avport == PS3AV_CMD_AVPORT_HDMI_0 ||	    avport == PS3AV_CMD_AVPORT_HDMI_1) {		switch (ch) {		case PS3AV_CMD_AUDIO_NUM_OF_CH_8:			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_8CH;			break;		case PS3AV_CMD_AUDIO_NUM_OF_CH_6:			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_6CH;			break;		case PS3AV_CMD_AUDIO_NUM_OF_CH_2:		default:			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;			break;		}	} else {		audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;	}	/* audio downmix permission */	audio->audio_downmix = PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED;	/* audio downmix level shift (0:0dB to 15:15dB) */	audio->audio_downmix_level = 0;	/* 0dB */	/* set ch status */	for (i = 0; i < 8; i++)		audio->audio_cs_info[i] = ps3av_mode_cs_info[i];	switch (fs) {	case PS3AV_CMD_AUDIO_FS_44K:		audio->audio_cs_info[3] &= ~CS_MASK;		audio->audio_cs_info[3] |= CS_44;		break;	case PS3AV_CMD_AUDIO_FS_88K:		audio->audio_cs_info[3] &= ~CS_MASK;		audio->audio_cs_info[3] |= CS_88;		break;	case PS3AV_CMD_AUDIO_FS_96K:		audio->audio_cs_info[3] &= ~CS_MASK;		audio->audio_cs_info[3] |= CS_96;		break;	case PS3AV_CMD_AUDIO_FS_176K:		audio->audio_cs_info[3] &= ~CS_MASK;		audio->audio_cs_info[3] |= CS_176;		break;	case PS3AV_CMD_AUDIO_FS_192K:		audio->audio_cs_info[3] &= ~CS_MASK;		audio->audio_cs_info[3] |= CS_192;		break;	default:		break;	}	/* pass through setting */	if (spdif_through &&	    (avport == PS3AV_CMD_AVPORT_SPDIF_0 ||	     avport == PS3AV_CMD_AVPORT_SPDIF_1)) {		audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;		audio->audio_source = PS3AV_CMD_AUDIO_SOURCE_SPDIF;		if (spdif_bitstream) {			audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;			audio->audio_cs_info[0] |= CS_BIT;		}	}}int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *audio_mode){	int res;	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MODE, sizeof(*audio_mode),			   sizeof(*audio_mode), &audio_mode->send_hdr);	if (res < 0)		return res;	res = get_status(audio_mode);	if (res)		printk(KERN_ERR "PS3AV_CID_AUDIO_MODE: failed %x\n", res);	return res;}int ps3av_cmd_audio_mute(int num_of_port, u32 *port, u32 mute){	int i, res;	struct ps3av_pkt_audio_mute audio_mute;	if (num_of_port > PS3AV_OPT_PORT_MAX)		return -EINVAL;	/* audio mute */	memset(&audio_mute, 0, sizeof(audio_mute));	for (i = 0; i < num_of_port; i++) {		audio_mute.mute[i].avport = port[i];		audio_mute.mute[i].mute = mute;	}	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE,			   sizeof(audio_mute.send_hdr) +			   sizeof(struct ps3av_audio_mute) * num_of_port,			   sizeof(audio_mute), &audio_mute.send_hdr);	if (res < 0)		return res;	res = get_status(&audio_mute);	if (res)		printk(KERN_ERR "PS3AV_CID_AUDIO_MUTE: failed %x\n", res);	return res;}int ps3av_cmd_audio_active(int active, u32 port){	int res;	struct ps3av_pkt_audio_active audio_active;	u32 cid;	/* audio active */	memset(&audio_active, 0, sizeof(audio_active));	audio_active.audio_port = port;	cid = active ? PS3AV_CID_AUDIO_ACTIVE : PS3AV_CID_AUDIO_INACTIVE;	res = ps3av_do_pkt(cid, sizeof(audio_active), sizeof(audio_active),			   &audio_active.send_hdr);	if (res < 0)		return res;	res = get_status(&audio_active);	if (res)		printk(KERN_ERR "PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid,		       res);	return res;}int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len){	int res;	ps3av_flip_ctl(0);	/* flip off */	/* avb packet */	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),			   &avb->send_hdr);	if (res < 0)		goto out;	res = get_status(avb);	if (res)		pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __func__,			 res);      out:	ps3av_flip_ctl(1);	/* flip on */	return res;}int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *hw_conf){	int res;	memset(hw_conf, 0, sizeof(*hw_conf));	res = ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF, sizeof(hw_conf->send_hdr),			   sizeof(*hw_conf), &hw_conf->send_hdr);	if (res < 0)		return res;	res = get_status(hw_conf);	if (res)		printk(KERN_ERR "PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res);	return res;}int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info,				     u32 avport){	int res;	memset(info, 0, sizeof(*info));	info->avport = avport;	res = ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO,			   sizeof(info->send_hdr) + sizeof(info->avport) +			   sizeof(info->reserved),			   sizeof(*info), &info->send_hdr);	if (res < 0)		return res;	res = get_status(info);	if (res)		printk(KERN_ERR "PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n",		       res);	return res;}#define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \		| PS3AV_CMD_AV_LAYOUT_44 \		| PS3AV_CMD_AV_LAYOUT_48)#define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \		| PS3AV_CMD_AV_LAYOUT_88 \		| PS3AV_CMD_AV_LAYOUT_96 \		| PS3AV_CMD_AV_LAYOUT_176 \		| PS3AV_CMD_AV_LAYOUT_192)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?