1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2006 Sony Computer Entertainment Inc.
4 * Copyright 2006, 2007 Sony Corporation
6 * AV backend support for PS3
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/delay.h>
13 #include <asm/ps3av.h>
15 #include <asm/ps3gpu.h>
19 static const struct video_fmt
{
22 } ps3av_video_fmt_table
[] = {
23 { PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT
, PS3AV_CMD_VIDEO_ORDER_RGB
},
24 { PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT
, PS3AV_CMD_VIDEO_ORDER_BGR
},
31 } ps3av_cs_video2av_table
[] = {
33 .cs
= PS3AV_CMD_VIDEO_CS_RGB_8
,
34 .av
= PS3AV_CMD_AV_CS_RGB_8
,
35 .bl
= PS3AV_CMD_AV_CS_8
37 .cs
= PS3AV_CMD_VIDEO_CS_RGB_10
,
38 .av
= PS3AV_CMD_AV_CS_RGB_8
,
39 .bl
= PS3AV_CMD_AV_CS_8
41 .cs
= PS3AV_CMD_VIDEO_CS_RGB_12
,
42 .av
= PS3AV_CMD_AV_CS_RGB_8
,
43 .bl
= PS3AV_CMD_AV_CS_8
45 .cs
= PS3AV_CMD_VIDEO_CS_YUV444_8
,
46 .av
= PS3AV_CMD_AV_CS_YUV444_8
,
47 .bl
= PS3AV_CMD_AV_CS_8
49 .cs
= PS3AV_CMD_VIDEO_CS_YUV444_10
,
50 .av
= PS3AV_CMD_AV_CS_YUV444_8
,
51 .bl
= PS3AV_CMD_AV_CS_10
53 .cs
= PS3AV_CMD_VIDEO_CS_YUV444_12
,
54 .av
= PS3AV_CMD_AV_CS_YUV444_8
,
55 .bl
= PS3AV_CMD_AV_CS_10
57 .cs
= PS3AV_CMD_VIDEO_CS_YUV422_8
,
58 .av
= PS3AV_CMD_AV_CS_YUV422_8
,
59 .bl
= PS3AV_CMD_AV_CS_10
61 .cs
= PS3AV_CMD_VIDEO_CS_YUV422_10
,
62 .av
= PS3AV_CMD_AV_CS_YUV422_8
,
63 .bl
= PS3AV_CMD_AV_CS_10
65 .cs
= PS3AV_CMD_VIDEO_CS_YUV422_12
,
66 .av
= PS3AV_CMD_AV_CS_YUV422_8
,
67 .bl
= PS3AV_CMD_AV_CS_12
69 .cs
= PS3AV_CMD_VIDEO_CS_XVYCC_8
,
70 .av
= PS3AV_CMD_AV_CS_XVYCC_8
,
71 .bl
= PS3AV_CMD_AV_CS_12
73 .cs
= PS3AV_CMD_VIDEO_CS_XVYCC_10
,
74 .av
= PS3AV_CMD_AV_CS_XVYCC_8
,
75 .bl
= PS3AV_CMD_AV_CS_12
77 .cs
= PS3AV_CMD_VIDEO_CS_XVYCC_12
,
78 .av
= PS3AV_CMD_AV_CS_XVYCC_8
,
79 .bl
= PS3AV_CMD_AV_CS_12
83 static u32
ps3av_cs_video2av(int cs
)
87 for (i
= 0; i
< ARRAY_SIZE(ps3av_cs_video2av_table
); i
++)
88 if (ps3av_cs_video2av_table
[i
].cs
== cs
)
89 return ps3av_cs_video2av_table
[i
].av
;
91 return PS3AV_CMD_AV_CS_RGB_8
;
94 static u32
ps3av_cs_video2av_bitlen(int cs
)
98 for (i
= 0; i
< ARRAY_SIZE(ps3av_cs_video2av_table
); i
++)
99 if (ps3av_cs_video2av_table
[i
].cs
== cs
)
100 return ps3av_cs_video2av_table
[i
].bl
;
102 return PS3AV_CMD_AV_CS_8
;
105 static const struct {
108 } ps3av_vid_video2av_table
[] = {
109 { PS3AV_CMD_VIDEO_VID_480I
, PS3AV_CMD_AV_VID_480I
},
110 { PS3AV_CMD_VIDEO_VID_480P
, PS3AV_CMD_AV_VID_480P
},
111 { PS3AV_CMD_VIDEO_VID_576I
, PS3AV_CMD_AV_VID_576I
},
112 { PS3AV_CMD_VIDEO_VID_576P
, PS3AV_CMD_AV_VID_576P
},
113 { PS3AV_CMD_VIDEO_VID_1080I_60HZ
, PS3AV_CMD_AV_VID_1080I_60HZ
},
114 { PS3AV_CMD_VIDEO_VID_720P_60HZ
, PS3AV_CMD_AV_VID_720P_60HZ
},
115 { PS3AV_CMD_VIDEO_VID_1080P_60HZ
, PS3AV_CMD_AV_VID_1080P_60HZ
},
116 { PS3AV_CMD_VIDEO_VID_1080I_50HZ
, PS3AV_CMD_AV_VID_1080I_50HZ
},
117 { PS3AV_CMD_VIDEO_VID_720P_50HZ
, PS3AV_CMD_AV_VID_720P_50HZ
},
118 { PS3AV_CMD_VIDEO_VID_1080P_50HZ
, PS3AV_CMD_AV_VID_1080P_50HZ
},
119 { PS3AV_CMD_VIDEO_VID_WXGA
, PS3AV_CMD_AV_VID_WXGA
},
120 { PS3AV_CMD_VIDEO_VID_SXGA
, PS3AV_CMD_AV_VID_SXGA
},
121 { PS3AV_CMD_VIDEO_VID_WUXGA
, PS3AV_CMD_AV_VID_WUXGA
}
124 static u32
ps3av_vid_video2av(int vid
)
128 for (i
= 0; i
< ARRAY_SIZE(ps3av_vid_video2av_table
); i
++)
129 if (ps3av_vid_video2av_table
[i
].vid
== vid
)
130 return ps3av_vid_video2av_table
[i
].av
;
132 return PS3AV_CMD_AV_VID_480P
;
135 static int ps3av_hdmi_range(void)
137 if (ps3_compare_firmware_version(1, 8, 0) < 0)
140 return 1; /* supported */
143 int ps3av_cmd_init(void)
146 struct ps3av_pkt_av_init av_init
;
147 struct ps3av_pkt_video_init video_init
;
148 struct ps3av_pkt_audio_init audio_init
;
151 memset(&video_init
, 0, sizeof(video_init
));
153 res
= ps3av_do_pkt(PS3AV_CID_VIDEO_INIT
, sizeof(video_init
.send_hdr
),
154 sizeof(video_init
), &video_init
.send_hdr
);
158 res
= get_status(&video_init
);
160 printk(KERN_ERR
"PS3AV_CID_VIDEO_INIT: failed %x\n", res
);
165 memset(&audio_init
, 0, sizeof(audio_init
));
167 res
= ps3av_do_pkt(PS3AV_CID_AUDIO_INIT
, sizeof(audio_init
.send_hdr
),
168 sizeof(audio_init
), &audio_init
.send_hdr
);
172 res
= get_status(&audio_init
);
174 printk(KERN_ERR
"PS3AV_CID_AUDIO_INIT: failed %x\n", res
);
179 memset(&av_init
, 0, sizeof(av_init
));
180 av_init
.event_bit
= 0;
182 res
= ps3av_do_pkt(PS3AV_CID_AV_INIT
, sizeof(av_init
), sizeof(av_init
),
187 res
= get_status(&av_init
);
189 printk(KERN_ERR
"PS3AV_CID_AV_INIT: failed %x\n", res
);
194 int ps3av_cmd_fin(void)
197 struct ps3av_pkt_av_fin av_fin
;
199 memset(&av_fin
, 0, sizeof(av_fin
));
201 res
= ps3av_do_pkt(PS3AV_CID_AV_FIN
, sizeof(av_fin
.send_hdr
),
202 sizeof(av_fin
), &av_fin
.send_hdr
);
206 res
= get_status(&av_fin
);
208 printk(KERN_ERR
"PS3AV_CID_AV_FIN: failed %x\n", res
);
213 int ps3av_cmd_av_video_mute(int num_of_port
, u32
*port
, u32 mute
)
215 int i
, send_len
, res
;
216 struct ps3av_pkt_av_video_mute av_video_mute
;
218 if (num_of_port
> PS3AV_MUTE_PORT_MAX
)
221 memset(&av_video_mute
, 0, sizeof(av_video_mute
));
222 for (i
= 0; i
< num_of_port
; i
++) {
223 av_video_mute
.mute
[i
].avport
= port
[i
];
224 av_video_mute
.mute
[i
].mute
= mute
;
227 send_len
= sizeof(av_video_mute
.send_hdr
) +
228 sizeof(struct ps3av_av_mute
) * num_of_port
;
229 res
= ps3av_do_pkt(PS3AV_CID_AV_VIDEO_MUTE
, send_len
,
230 sizeof(av_video_mute
), &av_video_mute
.send_hdr
);
234 res
= get_status(&av_video_mute
);
236 printk(KERN_ERR
"PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res
);
241 int ps3av_cmd_av_video_disable_sig(u32 port
)
244 struct ps3av_pkt_av_video_disable_sig av_video_sig
;
246 memset(&av_video_sig
, 0, sizeof(av_video_sig
));
247 av_video_sig
.avport
= port
;
249 res
= ps3av_do_pkt(PS3AV_CID_AV_VIDEO_DISABLE_SIG
,
250 sizeof(av_video_sig
), sizeof(av_video_sig
),
251 &av_video_sig
.send_hdr
);
255 res
= get_status(&av_video_sig
);
258 "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n",
264 int ps3av_cmd_av_tv_mute(u32 avport
, u32 mute
)
267 struct ps3av_pkt_av_tv_mute tv_mute
;
269 memset(&tv_mute
, 0, sizeof(tv_mute
));
270 tv_mute
.avport
= avport
;
273 res
= ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE
, sizeof(tv_mute
),
274 sizeof(tv_mute
), &tv_mute
.send_hdr
);
278 res
= get_status(&tv_mute
);
280 printk(KERN_ERR
"PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n",
286 int ps3av_cmd_enable_event(void)
289 struct ps3av_pkt_av_event av_event
;
291 memset(&av_event
, 0, sizeof(av_event
));
292 av_event
.event_bit
= PS3AV_CMD_EVENT_BIT_UNPLUGGED
|
293 PS3AV_CMD_EVENT_BIT_PLUGGED
| PS3AV_CMD_EVENT_BIT_HDCP_DONE
;
295 res
= ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT
, sizeof(av_event
),
296 sizeof(av_event
), &av_event
.send_hdr
);
300 res
= get_status(&av_event
);
302 printk(KERN_ERR
"PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res
);
307 int ps3av_cmd_av_hdmi_mode(u8 mode
)
310 struct ps3av_pkt_av_hdmi_mode hdmi_mode
;
312 memset(&hdmi_mode
, 0, sizeof(hdmi_mode
));
313 hdmi_mode
.mode
= mode
;
315 res
= ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE
, sizeof(hdmi_mode
),
316 sizeof(hdmi_mode
), &hdmi_mode
.send_hdr
);
320 res
= get_status(&hdmi_mode
);
321 if (res
&& res
!= PS3AV_STATUS_UNSUPPORTED_HDMI_MODE
)
322 printk(KERN_ERR
"PS3AV_CID_AV_HDMI_MODE: failed %x\n", res
);
327 u32
ps3av_cmd_set_av_video_cs(void *p
, u32 avport
, int video_vid
, int cs_out
,
330 struct ps3av_pkt_av_video_cs
*av_video_cs
;
332 av_video_cs
= (struct ps3av_pkt_av_video_cs
*)p
;
334 video_vid
= PS3AV_CMD_VIDEO_VID_720P_60HZ
;
336 cs_out
= PS3AV_CMD_VIDEO_CS_YUV444_8
;
340 memset(av_video_cs
, 0, sizeof(*av_video_cs
));
341 ps3av_set_hdr(PS3AV_CID_AV_VIDEO_CS
, sizeof(*av_video_cs
),
342 &av_video_cs
->send_hdr
);
343 av_video_cs
->avport
= avport
;
344 /* should be same as video_mode.resolution */
345 av_video_cs
->av_vid
= ps3av_vid_video2av(video_vid
);
346 av_video_cs
->av_cs_out
= ps3av_cs_video2av(cs_out
);
347 /* should be same as video_mode.video_cs_out */
348 av_video_cs
->av_cs_in
= ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8
);
349 av_video_cs
->bitlen_out
= ps3av_cs_video2av_bitlen(cs_out
);
350 if ((id
& PS3AV_MODE_WHITE
) && ps3av_hdmi_range())
351 av_video_cs
->super_white
= PS3AV_CMD_AV_SUPER_WHITE_ON
;
352 else /* default off */
353 av_video_cs
->super_white
= PS3AV_CMD_AV_SUPER_WHITE_OFF
;
354 av_video_cs
->aspect
= aspect
;
355 if (id
& PS3AV_MODE_DITHER
) {
356 av_video_cs
->dither
= PS3AV_CMD_AV_DITHER_ON
357 | PS3AV_CMD_AV_DITHER_8BIT
;
360 av_video_cs
->dither
= PS3AV_CMD_AV_DITHER_OFF
;
363 return sizeof(*av_video_cs
);
366 u32
ps3av_cmd_set_video_mode(void *p
, u32 head
, int video_vid
, int video_fmt
,
369 struct ps3av_pkt_video_mode
*video_mode
;
372 video_mode
= (struct ps3av_pkt_video_mode
*)p
;
374 video_vid
= PS3AV_CMD_VIDEO_VID_720P_60HZ
;
376 video_fmt
= PS3AV_CMD_VIDEO_FMT_X8R8G8B8
;
378 if (ps3av_video_mode2res(id
, &x
, &y
))
382 memset(video_mode
, 0, sizeof(*video_mode
));
383 ps3av_set_hdr(PS3AV_CID_VIDEO_MODE
, sizeof(*video_mode
),
384 &video_mode
->send_hdr
);
385 video_mode
->video_head
= head
;
386 if (video_vid
== PS3AV_CMD_VIDEO_VID_480I
387 && head
== PS3AV_CMD_VIDEO_HEAD_B
)
388 video_mode
->video_vid
= PS3AV_CMD_VIDEO_VID_480I_A
;
390 video_mode
->video_vid
= video_vid
;
391 video_mode
->width
= (u16
) x
;
392 video_mode
->height
= (u16
) y
;
393 video_mode
->pitch
= video_mode
->width
* 4; /* line_length */
394 video_mode
->video_out_format
= PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT
;
395 video_mode
->video_format
= ps3av_video_fmt_table
[video_fmt
].format
;
396 if ((id
& PS3AV_MODE_COLOR
) && ps3av_hdmi_range())
397 video_mode
->video_cl_cnv
= PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT
;
398 else /* default enable */
399 video_mode
->video_cl_cnv
= PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT
;
400 video_mode
->video_order
= ps3av_video_fmt_table
[video_fmt
].order
;
402 pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
403 __func__
, video_vid
, video_mode
->width
, video_mode
->height
,
404 video_mode
->pitch
, video_mode
->video_out_format
,
405 video_mode
->video_format
, video_mode
->video_order
);
406 return sizeof(*video_mode
);
409 int ps3av_cmd_video_format_black(u32 head
, u32 video_fmt
, u32 mute
)
412 struct ps3av_pkt_video_format video_format
;
414 memset(&video_format
, 0, sizeof(video_format
));
415 video_format
.video_head
= head
;
416 if (mute
!= PS3AV_CMD_MUTE_OFF
)
417 video_format
.video_format
= PS3AV_CMD_VIDEO_FORMAT_BLACK
;
419 video_format
.video_format
=
420 ps3av_video_fmt_table
[video_fmt
].format
;
421 video_format
.video_order
= ps3av_video_fmt_table
[video_fmt
].order
;
423 res
= ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT
, sizeof(video_format
),
424 sizeof(video_format
), &video_format
.send_hdr
);
428 res
= get_status(&video_format
);
430 printk(KERN_ERR
"PS3AV_CID_VIDEO_FORMAT: failed %x\n", res
);
436 int ps3av_cmd_av_audio_mute(int num_of_port
, u32
*port
, u32 mute
)
439 struct ps3av_pkt_av_audio_mute av_audio_mute
;
441 if (num_of_port
> PS3AV_MUTE_PORT_MAX
)
445 memset(&av_audio_mute
, 0, sizeof(av_audio_mute
));
446 for (i
= 0; i
< num_of_port
; i
++) {
447 av_audio_mute
.mute
[i
].avport
= port
[i
];
448 av_audio_mute
.mute
[i
].mute
= mute
;
451 res
= ps3av_do_pkt(PS3AV_CID_AV_AUDIO_MUTE
,
452 sizeof(av_audio_mute
.send_hdr
) +
453 sizeof(struct ps3av_av_mute
) * num_of_port
,
454 sizeof(av_audio_mute
), &av_audio_mute
.send_hdr
);
458 res
= get_status(&av_audio_mute
);
460 printk(KERN_ERR
"PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res
);
465 static const struct {
468 } ps3av_cnv_mclk_table
[] = {
469 { PS3AV_CMD_AUDIO_FS_44K
, PS3AV_CMD_AV_MCLK_512
},
470 { PS3AV_CMD_AUDIO_FS_48K
, PS3AV_CMD_AV_MCLK_512
},
471 { PS3AV_CMD_AUDIO_FS_88K
, PS3AV_CMD_AV_MCLK_256
},
472 { PS3AV_CMD_AUDIO_FS_96K
, PS3AV_CMD_AV_MCLK_256
},
473 { PS3AV_CMD_AUDIO_FS_176K
, PS3AV_CMD_AV_MCLK_128
},
474 { PS3AV_CMD_AUDIO_FS_192K
, PS3AV_CMD_AV_MCLK_128
}
477 static u8
ps3av_cnv_mclk(u32 fs
)
481 for (i
= 0; i
< ARRAY_SIZE(ps3av_cnv_mclk_table
); i
++)
482 if (ps3av_cnv_mclk_table
[i
].fs
== fs
)
483 return ps3av_cnv_mclk_table
[i
].mclk
;
485 printk(KERN_ERR
"%s failed, fs:%x\n", __func__
, fs
);
489 #define BASE PS3AV_CMD_AUDIO_FS_44K
491 static const u32 ps3av_ns_table
[][5] = {
492 /* D1, D2, D3, D4, D5 */
493 [PS3AV_CMD_AUDIO_FS_44K
-BASE
] = { 6272, 6272, 17836, 17836, 8918 },
494 [PS3AV_CMD_AUDIO_FS_48K
-BASE
] = { 6144, 6144, 11648, 11648, 5824 },
495 [PS3AV_CMD_AUDIO_FS_88K
-BASE
] = { 12544, 12544, 35672, 35672, 17836 },
496 [PS3AV_CMD_AUDIO_FS_96K
-BASE
] = { 12288, 12288, 23296, 23296, 11648 },
497 [PS3AV_CMD_AUDIO_FS_176K
-BASE
] = { 25088, 25088, 71344, 71344, 35672 },
498 [PS3AV_CMD_AUDIO_FS_192K
-BASE
] = { 24576, 24576, 46592, 46592, 23296 }
501 static void ps3av_cnv_ns(u8
*ns
, u32 fs
, u32 video_vid
)
507 av_vid
= ps3av_vid_video2av(video_vid
);
509 case PS3AV_CMD_AV_VID_480I
:
510 case PS3AV_CMD_AV_VID_576I
:
513 case PS3AV_CMD_AV_VID_480P
:
514 case PS3AV_CMD_AV_VID_576P
:
517 case PS3AV_CMD_AV_VID_1080I_60HZ
:
518 case PS3AV_CMD_AV_VID_1080I_50HZ
:
521 case PS3AV_CMD_AV_VID_720P_60HZ
:
522 case PS3AV_CMD_AV_VID_720P_50HZ
:
525 case PS3AV_CMD_AV_VID_1080P_60HZ
:
526 case PS3AV_CMD_AV_VID_1080P_50HZ
:
527 case PS3AV_CMD_AV_VID_WXGA
:
528 case PS3AV_CMD_AV_VID_SXGA
:
529 case PS3AV_CMD_AV_VID_WUXGA
:
533 printk(KERN_ERR
"%s failed, vid:%x\n", __func__
, video_vid
);
537 if (fs
< PS3AV_CMD_AUDIO_FS_44K
|| fs
> PS3AV_CMD_AUDIO_FS_192K
)
538 printk(KERN_ERR
"%s failed, fs:%x\n", __func__
, fs
);
540 ns_val
= ps3av_ns_table
[PS3AV_CMD_AUDIO_FS_44K
-BASE
][d
];
542 *ns
++ = ns_val
& 0x000000FF;
543 *ns
++ = (ns_val
& 0x0000FF00) >> 8;
544 *ns
= (ns_val
& 0x00FF0000) >> 16;
549 static u8
ps3av_cnv_enable(u32 source
, const u8
*enable
)
553 if (source
== PS3AV_CMD_AUDIO_SOURCE_SPDIF
) {
555 } else if (source
== PS3AV_CMD_AUDIO_SOURCE_SERIAL
) {
556 ret
= ((enable
[0] << 4) + (enable
[1] << 5) + (enable
[2] << 6) +
557 (enable
[3] << 7)) | 0x01;
559 printk(KERN_ERR
"%s failed, source:%x\n", __func__
, source
);
563 static u8
ps3av_cnv_fifomap(const u8
*map
)
567 ret
= map
[0] + (map
[1] << 2) + (map
[2] << 4) + (map
[3] << 6);
571 static u8
ps3av_cnv_inputlen(u32 word_bits
)
576 case PS3AV_CMD_AUDIO_WORD_BITS_16
:
577 ret
= PS3AV_CMD_AV_INPUTLEN_16
;
579 case PS3AV_CMD_AUDIO_WORD_BITS_20
:
580 ret
= PS3AV_CMD_AV_INPUTLEN_20
;
582 case PS3AV_CMD_AUDIO_WORD_BITS_24
:
583 ret
= PS3AV_CMD_AV_INPUTLEN_24
;
586 printk(KERN_ERR
"%s failed, word_bits:%x\n", __func__
,
593 static u8
ps3av_cnv_layout(u32 num_of_ch
)
595 if (num_of_ch
> PS3AV_CMD_AUDIO_NUM_OF_CH_8
) {
596 printk(KERN_ERR
"%s failed, num_of_ch:%x\n", __func__
,
601 return num_of_ch
== PS3AV_CMD_AUDIO_NUM_OF_CH_2
? 0x0 : 0x1;
604 static void ps3av_cnv_info(struct ps3av_audio_info_frame
*info
,
605 const struct ps3av_pkt_audio_mode
*mode
)
607 info
->pb1
.cc
= mode
->audio_num_of_ch
+ 1; /* CH2:0x01 --- CH8:0x07 */
612 info
->pb3
= 0; /* check mode->audio_format ?? */
613 info
->pb4
= mode
->audio_layout
;
614 info
->pb5
.dm
= mode
->audio_downmix
;
615 info
->pb5
.lsv
= mode
->audio_downmix_level
;
618 static void ps3av_cnv_chstat(u8
*chstat
, const u8
*cs_info
)
620 memcpy(chstat
, cs_info
, 5);
623 u32
ps3av_cmd_set_av_audio_param(void *p
, u32 port
,
624 const struct ps3av_pkt_audio_mode
*audio_mode
,
627 struct ps3av_pkt_av_audio_param
*param
;
629 param
= (struct ps3av_pkt_av_audio_param
*)p
;
631 memset(param
, 0, sizeof(*param
));
632 ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM
, sizeof(*param
),
635 param
->avport
= port
;
636 param
->mclk
= ps3av_cnv_mclk(audio_mode
->audio_fs
) | 0x80;
637 ps3av_cnv_ns(param
->ns
, audio_mode
->audio_fs
, video_vid
);
638 param
->enable
= ps3av_cnv_enable(audio_mode
->audio_source
,
639 audio_mode
->audio_enable
);
640 param
->swaplr
= 0x09;
641 param
->fifomap
= ps3av_cnv_fifomap(audio_mode
->audio_map
);
642 param
->inputctrl
= 0x49;
643 param
->inputlen
= ps3av_cnv_inputlen(audio_mode
->audio_word_bits
);
644 param
->layout
= ps3av_cnv_layout(audio_mode
->audio_num_of_ch
);
645 ps3av_cnv_info(¶m
->info
, audio_mode
);
646 ps3av_cnv_chstat(param
->chstat
, audio_mode
->audio_cs_info
);
648 return sizeof(*param
);
652 u8 ps3av_mode_cs_info
[] = {
653 0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
655 EXPORT_SYMBOL_GPL(ps3av_mode_cs_info
);
666 void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode
*audio
, u32 avport
,
667 u32 ch
, u32 fs
, u32 word_bits
, u32 format
,
673 if (!(ch
| fs
| format
| word_bits
| source
)) {
674 ch
= PS3AV_CMD_AUDIO_NUM_OF_CH_2
;
675 fs
= PS3AV_CMD_AUDIO_FS_48K
;
676 word_bits
= PS3AV_CMD_AUDIO_WORD_BITS_16
;
677 format
= PS3AV_CMD_AUDIO_FORMAT_PCM
;
678 source
= PS3AV_CMD_AUDIO_SOURCE_SERIAL
;
682 memset(audio
, 0, sizeof(*audio
));
683 ps3av_set_hdr(PS3AV_CID_AUDIO_MODE
, sizeof(*audio
), &audio
->send_hdr
);
685 audio
->avport
= (u8
) avport
;
686 audio
->mask
= 0x0FFF; /* XXX set all */
687 audio
->audio_num_of_ch
= ch
;
688 audio
->audio_fs
= fs
;
689 audio
->audio_word_bits
= word_bits
;
690 audio
->audio_format
= format
;
691 audio
->audio_source
= source
;
694 case PS3AV_CMD_AUDIO_NUM_OF_CH_8
:
695 audio
->audio_enable
[3] = 1;
697 case PS3AV_CMD_AUDIO_NUM_OF_CH_6
:
698 audio
->audio_enable
[2] = 1;
699 audio
->audio_enable
[1] = 1;
701 case PS3AV_CMD_AUDIO_NUM_OF_CH_2
:
703 audio
->audio_enable
[0] = 1;
707 for (i
= 0; i
< 4; i
++)
708 audio
->audio_swap
[i
] = PS3AV_CMD_AUDIO_SWAP_0
; /* no swap */
710 /* audio serial input mapping */
711 audio
->audio_map
[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0
;
712 audio
->audio_map
[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1
;
713 audio
->audio_map
[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2
;
714 audio
->audio_map
[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3
;
716 /* audio speaker layout */
717 if (avport
== PS3AV_CMD_AVPORT_HDMI_0
||
718 avport
== PS3AV_CMD_AVPORT_HDMI_1
) {
720 case PS3AV_CMD_AUDIO_NUM_OF_CH_8
:
721 audio
->audio_layout
= PS3AV_CMD_AUDIO_LAYOUT_8CH
;
723 case PS3AV_CMD_AUDIO_NUM_OF_CH_6
:
724 audio
->audio_layout
= PS3AV_CMD_AUDIO_LAYOUT_6CH
;
726 case PS3AV_CMD_AUDIO_NUM_OF_CH_2
:
728 audio
->audio_layout
= PS3AV_CMD_AUDIO_LAYOUT_2CH
;
732 audio
->audio_layout
= PS3AV_CMD_AUDIO_LAYOUT_2CH
;
735 /* audio downmix permission */
736 audio
->audio_downmix
= PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED
;
737 /* audio downmix level shift (0:0dB to 15:15dB) */
738 audio
->audio_downmix_level
= 0; /* 0dB */
741 for (i
= 0; i
< 8; i
++)
742 audio
->audio_cs_info
[i
] = ps3av_mode_cs_info
[i
];
745 case PS3AV_CMD_AUDIO_FS_44K
:
746 audio
->audio_cs_info
[3] &= ~CS_MASK
;
747 audio
->audio_cs_info
[3] |= CS_44
;
749 case PS3AV_CMD_AUDIO_FS_88K
:
750 audio
->audio_cs_info
[3] &= ~CS_MASK
;
751 audio
->audio_cs_info
[3] |= CS_88
;
753 case PS3AV_CMD_AUDIO_FS_96K
:
754 audio
->audio_cs_info
[3] &= ~CS_MASK
;
755 audio
->audio_cs_info
[3] |= CS_96
;
757 case PS3AV_CMD_AUDIO_FS_176K
:
758 audio
->audio_cs_info
[3] &= ~CS_MASK
;
759 audio
->audio_cs_info
[3] |= CS_176
;
761 case PS3AV_CMD_AUDIO_FS_192K
:
762 audio
->audio_cs_info
[3] &= ~CS_MASK
;
763 audio
->audio_cs_info
[3] |= CS_192
;
770 spdif_through
= audio
->audio_cs_info
[0] & 0x02;
772 /* pass through setting */
774 (avport
== PS3AV_CMD_AVPORT_SPDIF_0
||
775 avport
== PS3AV_CMD_AVPORT_SPDIF_1
||
776 avport
== PS3AV_CMD_AVPORT_HDMI_0
||
777 avport
== PS3AV_CMD_AVPORT_HDMI_1
)) {
778 audio
->audio_word_bits
= PS3AV_CMD_AUDIO_WORD_BITS_16
;
779 audio
->audio_format
= PS3AV_CMD_AUDIO_FORMAT_BITSTREAM
;
783 int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode
*audio_mode
)
787 res
= ps3av_do_pkt(PS3AV_CID_AUDIO_MODE
, sizeof(*audio_mode
),
788 sizeof(*audio_mode
), &audio_mode
->send_hdr
);
792 res
= get_status(audio_mode
);
794 printk(KERN_ERR
"PS3AV_CID_AUDIO_MODE: failed %x\n", res
);
799 int ps3av_cmd_audio_mute(int num_of_port
, u32
*port
, u32 mute
)
802 struct ps3av_pkt_audio_mute audio_mute
;
804 if (num_of_port
> PS3AV_OPT_PORT_MAX
)
808 memset(&audio_mute
, 0, sizeof(audio_mute
));
809 for (i
= 0; i
< num_of_port
; i
++) {
810 audio_mute
.mute
[i
].avport
= port
[i
];
811 audio_mute
.mute
[i
].mute
= mute
;
814 res
= ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE
,
815 sizeof(audio_mute
.send_hdr
) +
816 sizeof(struct ps3av_audio_mute
) * num_of_port
,
817 sizeof(audio_mute
), &audio_mute
.send_hdr
);
821 res
= get_status(&audio_mute
);
823 printk(KERN_ERR
"PS3AV_CID_AUDIO_MUTE: failed %x\n", res
);
828 int ps3av_cmd_audio_active(int active
, u32 port
)
831 struct ps3av_pkt_audio_active audio_active
;
835 memset(&audio_active
, 0, sizeof(audio_active
));
836 audio_active
.audio_port
= port
;
837 cid
= active
? PS3AV_CID_AUDIO_ACTIVE
: PS3AV_CID_AUDIO_INACTIVE
;
839 res
= ps3av_do_pkt(cid
, sizeof(audio_active
), sizeof(audio_active
),
840 &audio_active
.send_hdr
);
844 res
= get_status(&audio_active
);
846 printk(KERN_ERR
"PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid
,
852 int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param
*avb
, u32 send_len
)
856 mutex_lock(&ps3_gpu_mutex
);
859 res
= ps3av_do_pkt(PS3AV_CID_AVB_PARAM
, send_len
, sizeof(*avb
),
864 res
= get_status(avb
);
866 pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __func__
,
870 mutex_unlock(&ps3_gpu_mutex
);
874 int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf
*hw_conf
)
878 memset(hw_conf
, 0, sizeof(*hw_conf
));
880 res
= ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF
, sizeof(hw_conf
->send_hdr
),
881 sizeof(*hw_conf
), &hw_conf
->send_hdr
);
885 res
= get_status(hw_conf
);
887 printk(KERN_ERR
"PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res
);
892 int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info
*info
,
897 memset(info
, 0, sizeof(*info
));
898 info
->avport
= avport
;
900 res
= ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO
,
901 sizeof(info
->send_hdr
) + sizeof(info
->avport
) +
902 sizeof(info
->reserved
),
903 sizeof(*info
), &info
->send_hdr
);
907 res
= get_status(info
);
909 printk(KERN_ERR
"PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n",
915 #define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \
916 | PS3AV_CMD_AV_LAYOUT_44 \
917 | PS3AV_CMD_AV_LAYOUT_48)
919 #define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \
920 | PS3AV_CMD_AV_LAYOUT_88 \
921 | PS3AV_CMD_AV_LAYOUT_96 \
922 | PS3AV_CMD_AV_LAYOUT_176 \
923 | PS3AV_CMD_AV_LAYOUT_192)