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), ¶m->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(¶m->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 + -
显示快捷键?