2 * Copyright (C) 2006 Sony Computer Entertainment Inc.
3 * Copyright 2006, 2007 Sony Corporation
5 * AV backend support for PS3
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/delay.h>
24 #include <asm/ps3av.h>
29 static const struct video_fmt
{
32 } ps3av_video_fmt_table
[] = {
33 { PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT
, PS3AV_CMD_VIDEO_ORDER_RGB
},
34 { PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT
, PS3AV_CMD_VIDEO_ORDER_BGR
},
41 } ps3av_cs_video2av_table
[] = {
43 .cs
= PS3AV_CMD_VIDEO_CS_RGB_8
,
44 .av
= PS3AV_CMD_AV_CS_RGB_8
,
45 .bl
= PS3AV_CMD_AV_CS_8
47 .cs
= PS3AV_CMD_VIDEO_CS_RGB_10
,
48 .av
= PS3AV_CMD_AV_CS_RGB_8
,
49 .bl
= PS3AV_CMD_AV_CS_8
51 .cs
= PS3AV_CMD_VIDEO_CS_RGB_12
,
52 .av
= PS3AV_CMD_AV_CS_RGB_8
,
53 .bl
= PS3AV_CMD_AV_CS_8
55 .cs
= PS3AV_CMD_VIDEO_CS_YUV444_8
,
56 .av
= PS3AV_CMD_AV_CS_YUV444_8
,
57 .bl
= PS3AV_CMD_AV_CS_8
59 .cs
= PS3AV_CMD_VIDEO_CS_YUV444_10
,
60 .av
= PS3AV_CMD_AV_CS_YUV444_8
,
61 .bl
= PS3AV_CMD_AV_CS_10
63 .cs
= PS3AV_CMD_VIDEO_CS_YUV444_12
,
64 .av
= PS3AV_CMD_AV_CS_YUV444_8
,
65 .bl
= PS3AV_CMD_AV_CS_10
67 .cs
= PS3AV_CMD_VIDEO_CS_YUV422_8
,
68 .av
= PS3AV_CMD_AV_CS_YUV422_8
,
69 .bl
= PS3AV_CMD_AV_CS_10
71 .cs
= PS3AV_CMD_VIDEO_CS_YUV422_10
,
72 .av
= PS3AV_CMD_AV_CS_YUV422_8
,
73 .bl
= PS3AV_CMD_AV_CS_10
75 .cs
= PS3AV_CMD_VIDEO_CS_YUV422_12
,
76 .av
= PS3AV_CMD_AV_CS_YUV422_8
,
77 .bl
= PS3AV_CMD_AV_CS_12
79 .cs
= PS3AV_CMD_VIDEO_CS_XVYCC_8
,
80 .av
= PS3AV_CMD_AV_CS_XVYCC_8
,
81 .bl
= PS3AV_CMD_AV_CS_12
83 .cs
= PS3AV_CMD_VIDEO_CS_XVYCC_10
,
84 .av
= PS3AV_CMD_AV_CS_XVYCC_8
,
85 .bl
= PS3AV_CMD_AV_CS_12
87 .cs
= PS3AV_CMD_VIDEO_CS_XVYCC_12
,
88 .av
= PS3AV_CMD_AV_CS_XVYCC_8
,
89 .bl
= PS3AV_CMD_AV_CS_12
93 static u32
ps3av_cs_video2av(int cs
)
97 for (i
= 0; i
< ARRAY_SIZE(ps3av_cs_video2av_table
); i
++)
98 if (ps3av_cs_video2av_table
[i
].cs
== cs
)
99 return ps3av_cs_video2av_table
[i
].av
;
101 return PS3AV_CMD_AV_CS_RGB_8
;
104 static u32
ps3av_cs_video2av_bitlen(int cs
)
108 for (i
= 0; i
< ARRAY_SIZE(ps3av_cs_video2av_table
); i
++)
109 if (ps3av_cs_video2av_table
[i
].cs
== cs
)
110 return ps3av_cs_video2av_table
[i
].bl
;
112 return PS3AV_CMD_AV_CS_8
;
115 static const struct {
118 } ps3av_vid_video2av_table
[] = {
119 { PS3AV_CMD_VIDEO_VID_480I
, PS3AV_CMD_AV_VID_480I
},
120 { PS3AV_CMD_VIDEO_VID_480P
, PS3AV_CMD_AV_VID_480P
},
121 { PS3AV_CMD_VIDEO_VID_576I
, PS3AV_CMD_AV_VID_576I
},
122 { PS3AV_CMD_VIDEO_VID_576P
, PS3AV_CMD_AV_VID_576P
},
123 { PS3AV_CMD_VIDEO_VID_1080I_60HZ
, PS3AV_CMD_AV_VID_1080I_60HZ
},
124 { PS3AV_CMD_VIDEO_VID_720P_60HZ
, PS3AV_CMD_AV_VID_720P_60HZ
},
125 { PS3AV_CMD_VIDEO_VID_1080P_60HZ
, PS3AV_CMD_AV_VID_1080P_60HZ
},
126 { PS3AV_CMD_VIDEO_VID_1080I_50HZ
, PS3AV_CMD_AV_VID_1080I_50HZ
},
127 { PS3AV_CMD_VIDEO_VID_720P_50HZ
, PS3AV_CMD_AV_VID_720P_50HZ
},
128 { PS3AV_CMD_VIDEO_VID_1080P_50HZ
, PS3AV_CMD_AV_VID_1080P_50HZ
},
129 { PS3AV_CMD_VIDEO_VID_WXGA
, PS3AV_CMD_AV_VID_WXGA
},
130 { PS3AV_CMD_VIDEO_VID_SXGA
, PS3AV_CMD_AV_VID_SXGA
},
131 { PS3AV_CMD_VIDEO_VID_WUXGA
, PS3AV_CMD_AV_VID_WUXGA
}
134 static u32
ps3av_vid_video2av(int vid
)
138 for (i
= 0; i
< ARRAY_SIZE(ps3av_vid_video2av_table
); i
++)
139 if (ps3av_vid_video2av_table
[i
].vid
== vid
)
140 return ps3av_vid_video2av_table
[i
].av
;
142 return PS3AV_CMD_AV_VID_480P
;
145 int ps3av_cmd_init(void)
148 struct ps3av_pkt_av_init av_init
;
149 struct ps3av_pkt_video_init video_init
;
150 struct ps3av_pkt_audio_init audio_init
;
153 memset(&video_init
, 0, sizeof(video_init
));
155 res
= ps3av_do_pkt(PS3AV_CID_VIDEO_INIT
, sizeof(video_init
.send_hdr
),
156 sizeof(video_init
), &video_init
.send_hdr
);
160 res
= get_status(&video_init
);
162 printk(KERN_ERR
"PS3AV_CID_VIDEO_INIT: failed %x\n", res
);
167 memset(&audio_init
, 0, sizeof(audio_init
));
169 res
= ps3av_do_pkt(PS3AV_CID_AUDIO_INIT
, sizeof(audio_init
.send_hdr
),
170 sizeof(audio_init
), &audio_init
.send_hdr
);
174 res
= get_status(&audio_init
);
176 printk(KERN_ERR
"PS3AV_CID_AUDIO_INIT: failed %x\n", res
);
181 memset(&av_init
, 0, sizeof(av_init
));
182 av_init
.event_bit
= 0;
184 res
= ps3av_do_pkt(PS3AV_CID_AV_INIT
, sizeof(av_init
), sizeof(av_init
),
189 res
= get_status(&av_init
);
191 printk(KERN_ERR
"PS3AV_CID_AV_INIT: failed %x\n", res
);
196 int ps3av_cmd_fin(void)
199 struct ps3av_pkt_av_fin av_fin
;
201 memset(&av_fin
, 0, sizeof(av_fin
));
203 res
= ps3av_do_pkt(PS3AV_CID_AV_FIN
, sizeof(av_fin
.send_hdr
),
204 sizeof(av_fin
), &av_fin
.send_hdr
);
208 res
= get_status(&av_fin
);
210 printk(KERN_ERR
"PS3AV_CID_AV_FIN: failed %x\n", res
);
215 int ps3av_cmd_av_video_mute(int num_of_port
, u32
*port
, u32 mute
)
217 int i
, send_len
, res
;
218 struct ps3av_pkt_av_video_mute av_video_mute
;
220 if (num_of_port
> PS3AV_MUTE_PORT_MAX
)
223 memset(&av_video_mute
, 0, sizeof(av_video_mute
));
224 for (i
= 0; i
< num_of_port
; i
++) {
225 av_video_mute
.mute
[i
].avport
= port
[i
];
226 av_video_mute
.mute
[i
].mute
= mute
;
229 send_len
= sizeof(av_video_mute
.send_hdr
) +
230 sizeof(struct ps3av_av_mute
) * num_of_port
;
231 res
= ps3av_do_pkt(PS3AV_CID_AV_VIDEO_MUTE
, send_len
,
232 sizeof(av_video_mute
), &av_video_mute
.send_hdr
);
236 res
= get_status(&av_video_mute
);
238 printk(KERN_ERR
"PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res
);
243 int ps3av_cmd_av_video_disable_sig(u32 port
)
246 struct ps3av_pkt_av_video_disable_sig av_video_sig
;
248 memset(&av_video_sig
, 0, sizeof(av_video_sig
));
249 av_video_sig
.avport
= port
;
251 res
= ps3av_do_pkt(PS3AV_CID_AV_VIDEO_DISABLE_SIG
,
252 sizeof(av_video_sig
), sizeof(av_video_sig
),
253 &av_video_sig
.send_hdr
);
257 res
= get_status(&av_video_sig
);
260 "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n",
266 int ps3av_cmd_av_tv_mute(u32 avport
, u32 mute
)
269 struct ps3av_pkt_av_tv_mute tv_mute
;
271 memset(&tv_mute
, 0, sizeof(tv_mute
));
272 tv_mute
.avport
= avport
;
275 res
= ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE
, sizeof(tv_mute
),
276 sizeof(tv_mute
), &tv_mute
.send_hdr
);
280 res
= get_status(&tv_mute
);
282 printk(KERN_ERR
"PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n",
288 int ps3av_cmd_enable_event(void)
291 struct ps3av_pkt_av_event av_event
;
293 memset(&av_event
, 0, sizeof(av_event
));
294 av_event
.event_bit
= PS3AV_CMD_EVENT_BIT_UNPLUGGED
|
295 PS3AV_CMD_EVENT_BIT_PLUGGED
| PS3AV_CMD_EVENT_BIT_HDCP_DONE
;
297 res
= ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT
, sizeof(av_event
),
298 sizeof(av_event
), &av_event
.send_hdr
);
302 res
= get_status(&av_event
);
304 printk(KERN_ERR
"PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res
);
309 int ps3av_cmd_av_hdmi_mode(u8 mode
)
312 struct ps3av_pkt_av_hdmi_mode hdmi_mode
;
314 memset(&hdmi_mode
, 0, sizeof(hdmi_mode
));
315 hdmi_mode
.mode
= mode
;
317 res
= ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE
, sizeof(hdmi_mode
),
318 sizeof(hdmi_mode
), &hdmi_mode
.send_hdr
);
322 res
= get_status(&hdmi_mode
);
323 if (res
&& res
!= PS3AV_STATUS_UNSUPPORTED_HDMI_MODE
)
324 printk(KERN_ERR
"PS3AV_CID_AV_HDMI_MODE: failed %x\n", res
);
329 u32
ps3av_cmd_set_av_video_cs(void *p
, u32 avport
, int video_vid
, int cs_out
,
332 struct ps3av_pkt_av_video_cs
*av_video_cs
;
334 av_video_cs
= (struct ps3av_pkt_av_video_cs
*)p
;
336 video_vid
= PS3AV_CMD_VIDEO_VID_720P_60HZ
;
338 cs_out
= PS3AV_CMD_VIDEO_CS_YUV444_8
;
342 memset(av_video_cs
, 0, sizeof(*av_video_cs
));
343 ps3av_set_hdr(PS3AV_CID_AV_VIDEO_CS
, sizeof(*av_video_cs
),
344 &av_video_cs
->send_hdr
);
345 av_video_cs
->avport
= avport
;
346 /* should be same as video_mode.resolution */
347 av_video_cs
->av_vid
= ps3av_vid_video2av(video_vid
);
348 av_video_cs
->av_cs_out
= ps3av_cs_video2av(cs_out
);
349 /* should be same as video_mode.video_cs_out */
350 av_video_cs
->av_cs_in
= ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8
);
351 av_video_cs
->bitlen_out
= ps3av_cs_video2av_bitlen(cs_out
);
352 av_video_cs
->aspect
= aspect
;
353 if (id
& PS3AV_MODE_DITHER
) {
354 av_video_cs
->dither
= PS3AV_CMD_AV_DITHER_ON
355 | PS3AV_CMD_AV_DITHER_8BIT
;
358 av_video_cs
->dither
= PS3AV_CMD_AV_DITHER_OFF
;
361 return sizeof(*av_video_cs
);
364 u32
ps3av_cmd_set_video_mode(void *p
, u32 head
, int video_vid
, int video_fmt
,
367 struct ps3av_pkt_video_mode
*video_mode
;
370 video_mode
= (struct ps3av_pkt_video_mode
*)p
;
372 video_vid
= PS3AV_CMD_VIDEO_VID_720P_60HZ
;
374 video_fmt
= PS3AV_CMD_VIDEO_FMT_X8R8G8B8
;
376 if (ps3av_video_mode2res(id
, &x
, &y
))
380 memset(video_mode
, 0, sizeof(*video_mode
));
381 ps3av_set_hdr(PS3AV_CID_VIDEO_MODE
, sizeof(*video_mode
),
382 &video_mode
->send_hdr
);
383 video_mode
->video_head
= head
;
384 if (video_vid
== PS3AV_CMD_VIDEO_VID_480I
385 && head
== PS3AV_CMD_VIDEO_HEAD_B
)
386 video_mode
->video_vid
= PS3AV_CMD_VIDEO_VID_480I_A
;
388 video_mode
->video_vid
= video_vid
;
389 video_mode
->width
= (u16
) x
;
390 video_mode
->height
= (u16
) y
;
391 video_mode
->pitch
= video_mode
->width
* 4; /* line_length */
392 video_mode
->video_out_format
= PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT
;
393 video_mode
->video_format
= ps3av_video_fmt_table
[video_fmt
].format
;
394 video_mode
->video_order
= ps3av_video_fmt_table
[video_fmt
].order
;
396 pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
397 __FUNCTION__
, video_vid
, video_mode
->width
, video_mode
->height
,
398 video_mode
->pitch
, video_mode
->video_out_format
,
399 video_mode
->video_format
, video_mode
->video_order
);
400 return sizeof(*video_mode
);
403 int ps3av_cmd_video_format_black(u32 head
, u32 video_fmt
, u32 mute
)
406 struct ps3av_pkt_video_format video_format
;
408 memset(&video_format
, 0, sizeof(video_format
));
409 video_format
.video_head
= head
;
410 if (mute
!= PS3AV_CMD_MUTE_OFF
)
411 video_format
.video_format
= PS3AV_CMD_VIDEO_FORMAT_BLACK
;
413 video_format
.video_format
=
414 ps3av_video_fmt_table
[video_fmt
].format
;
415 video_format
.video_order
= ps3av_video_fmt_table
[video_fmt
].order
;
417 res
= ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT
, sizeof(video_format
),
418 sizeof(video_format
), &video_format
.send_hdr
);
422 res
= get_status(&video_format
);
424 printk(KERN_ERR
"PS3AV_CID_VIDEO_FORMAT: failed %x\n", res
);
430 int ps3av_cmd_av_audio_mute(int num_of_port
, u32
*port
, u32 mute
)
433 struct ps3av_pkt_av_audio_mute av_audio_mute
;
435 if (num_of_port
> PS3AV_MUTE_PORT_MAX
)
439 memset(&av_audio_mute
, 0, sizeof(av_audio_mute
));
440 for (i
= 0; i
< num_of_port
; i
++) {
441 av_audio_mute
.mute
[i
].avport
= port
[i
];
442 av_audio_mute
.mute
[i
].mute
= mute
;
445 res
= ps3av_do_pkt(PS3AV_CID_AV_AUDIO_MUTE
,
446 sizeof(av_audio_mute
.send_hdr
) +
447 sizeof(struct ps3av_av_mute
) * num_of_port
,
448 sizeof(av_audio_mute
), &av_audio_mute
.send_hdr
);
452 res
= get_status(&av_audio_mute
);
454 printk(KERN_ERR
"PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res
);
459 static const struct {
462 } ps3av_cnv_mclk_table
[] = {
463 { PS3AV_CMD_AUDIO_FS_44K
, PS3AV_CMD_AV_MCLK_512
},
464 { PS3AV_CMD_AUDIO_FS_48K
, PS3AV_CMD_AV_MCLK_512
},
465 { PS3AV_CMD_AUDIO_FS_88K
, PS3AV_CMD_AV_MCLK_256
},
466 { PS3AV_CMD_AUDIO_FS_96K
, PS3AV_CMD_AV_MCLK_256
},
467 { PS3AV_CMD_AUDIO_FS_176K
, PS3AV_CMD_AV_MCLK_128
},
468 { PS3AV_CMD_AUDIO_FS_192K
, PS3AV_CMD_AV_MCLK_128
}
471 static u8
ps3av_cnv_mclk(u32 fs
)
475 for (i
= 0; i
< ARRAY_SIZE(ps3av_cnv_mclk_table
); i
++)
476 if (ps3av_cnv_mclk_table
[i
].fs
== fs
)
477 return ps3av_cnv_mclk_table
[i
].mclk
;
479 printk(KERN_ERR
"%s failed, fs:%x\n", __FUNCTION__
, fs
);
483 #define BASE PS3AV_CMD_AUDIO_FS_44K
485 static const u32 ps3av_ns_table
[][5] = {
486 /* D1, D2, D3, D4, D5 */
487 [PS3AV_CMD_AUDIO_FS_44K
-BASE
] { 6272, 6272, 17836, 17836, 8918 },
488 [PS3AV_CMD_AUDIO_FS_48K
-BASE
] { 6144, 6144, 11648, 11648, 5824 },
489 [PS3AV_CMD_AUDIO_FS_88K
-BASE
] { 12544, 12544, 35672, 35672, 17836 },
490 [PS3AV_CMD_AUDIO_FS_96K
-BASE
] { 12288, 12288, 23296, 23296, 11648 },
491 [PS3AV_CMD_AUDIO_FS_176K
-BASE
] { 25088, 25088, 71344, 71344, 35672 },
492 [PS3AV_CMD_AUDIO_FS_192K
-BASE
] { 24576, 24576, 46592, 46592, 23296 }
495 static void ps3av_cnv_ns(u8
*ns
, u32 fs
, u32 video_vid
)
502 av_vid
= ps3av_vid_video2av(video_vid
);
504 case PS3AV_CMD_AV_VID_480I
:
505 case PS3AV_CMD_AV_VID_576I
:
508 case PS3AV_CMD_AV_VID_480P
:
509 case PS3AV_CMD_AV_VID_576P
:
512 case PS3AV_CMD_AV_VID_1080I_60HZ
:
513 case PS3AV_CMD_AV_VID_1080I_50HZ
:
516 case PS3AV_CMD_AV_VID_720P_60HZ
:
517 case PS3AV_CMD_AV_VID_720P_50HZ
:
520 case PS3AV_CMD_AV_VID_1080P_60HZ
:
521 case PS3AV_CMD_AV_VID_1080P_50HZ
:
522 case PS3AV_CMD_AV_VID_WXGA
:
523 case PS3AV_CMD_AV_VID_SXGA
:
524 case PS3AV_CMD_AV_VID_WUXGA
:
528 printk(KERN_ERR
"%s failed, vid:%x\n", __FUNCTION__
,
533 if (fs
< PS3AV_CMD_AUDIO_FS_44K
|| fs
> PS3AV_CMD_AUDIO_FS_192K
)
534 printk(KERN_ERR
"%s failed, fs:%x\n", __FUNCTION__
, fs
);
536 ns_val
= ps3av_ns_table
[PS3AV_CMD_AUDIO_FS_44K
-BASE
][d
];
538 *p
++ = ns_val
& 0x000000FF;
539 *p
++ = (ns_val
& 0x0000FF00) >> 8;
540 *p
= (ns_val
& 0x00FF0000) >> 16;
545 static u8
ps3av_cnv_enable(u32 source
, u8
*enable
)
549 if (source
== PS3AV_CMD_AUDIO_SOURCE_SPDIF
) {
551 } else if (source
== PS3AV_CMD_AUDIO_SOURCE_SERIAL
) {
553 ret
= ((p
[0] << 4) + (p
[1] << 5) + (p
[2] << 6) + (p
[3] << 7)) |
556 printk(KERN_ERR
"%s failed, source:%x\n", __FUNCTION__
,
561 static u8
ps3av_cnv_fifomap(u8
*map
)
566 ret
= p
[0] + (p
[1] << 2) + (p
[2] << 4) + (p
[3] << 6);
570 static u8
ps3av_cnv_inputlen(u32 word_bits
)
575 case PS3AV_CMD_AUDIO_WORD_BITS_16
:
576 ret
= PS3AV_CMD_AV_INPUTLEN_16
;
578 case PS3AV_CMD_AUDIO_WORD_BITS_20
:
579 ret
= PS3AV_CMD_AV_INPUTLEN_20
;
581 case PS3AV_CMD_AUDIO_WORD_BITS_24
:
582 ret
= PS3AV_CMD_AV_INPUTLEN_24
;
585 printk(KERN_ERR
"%s failed, word_bits:%x\n", __FUNCTION__
,
592 static u8
ps3av_cnv_layout(u32 num_of_ch
)
594 if (num_of_ch
> PS3AV_CMD_AUDIO_NUM_OF_CH_8
) {
595 printk(KERN_ERR
"%s failed, num_of_ch:%x\n", __FUNCTION__
,
600 return num_of_ch
== PS3AV_CMD_AUDIO_NUM_OF_CH_2
? 0x0 : 0x1;
603 static void ps3av_cnv_info(struct ps3av_audio_info_frame
*info
,
604 const struct ps3av_pkt_audio_mode
*mode
)
606 info
->pb1
.cc
= mode
->audio_num_of_ch
+ 1; /* CH2:0x01 --- CH8:0x07 */
611 info
->pb3
= 0; /* check mode->audio_format ?? */
612 info
->pb4
= mode
->audio_layout
;
613 info
->pb5
.dm
= mode
->audio_downmix
;
614 info
->pb5
.lsv
= mode
->audio_downmix_level
;
617 static void ps3av_cnv_chstat(u8
*chstat
, u8
*cs_info
)
619 memcpy(chstat
, cs_info
, 5);
622 u32
ps3av_cmd_set_av_audio_param(void *p
, u32 port
,
623 const struct ps3av_pkt_audio_mode
*audio_mode
,
626 struct ps3av_pkt_av_audio_param
*param
;
628 param
= (struct ps3av_pkt_av_audio_param
*)p
;
630 memset(param
, 0, sizeof(*param
));
631 ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM
, sizeof(*param
),
634 param
->avport
= port
;
635 param
->mclk
= ps3av_cnv_mclk(audio_mode
->audio_fs
) | 0x80;
636 ps3av_cnv_ns(param
->ns
, audio_mode
->audio_fs
, video_vid
);
637 param
->enable
= ps3av_cnv_enable(audio_mode
->audio_source
,
638 audio_mode
->audio_enable
);
639 param
->swaplr
= 0x09;
640 param
->fifomap
= ps3av_cnv_fifomap(audio_mode
->audio_map
);
641 param
->inputctrl
= 0x49;
642 param
->inputlen
= ps3av_cnv_inputlen(audio_mode
->audio_word_bits
);
643 param
->layout
= ps3av_cnv_layout(audio_mode
->audio_num_of_ch
);
644 ps3av_cnv_info(¶m
->info
, audio_mode
);
645 ps3av_cnv_chstat(param
->chstat
, audio_mode
->audio_cs_info
);
647 return sizeof(*param
);
651 static const u8 ps3av_mode_cs_info
[] = {
652 0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
664 void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode
*audio
, u32 avport
,
665 u32 ch
, u32 fs
, u32 word_bits
, u32 format
,
668 int spdif_through
, spdif_bitstream
;
671 if (!(ch
| fs
| format
| word_bits
| source
)) {
672 ch
= PS3AV_CMD_AUDIO_NUM_OF_CH_2
;
673 fs
= PS3AV_CMD_AUDIO_FS_48K
;
674 word_bits
= PS3AV_CMD_AUDIO_WORD_BITS_16
;
675 format
= PS3AV_CMD_AUDIO_FORMAT_PCM
;
676 source
= PS3AV_CMD_AUDIO_SOURCE_SERIAL
;
678 spdif_through
= spdif_bitstream
= 0; /* XXX not supported */
681 memset(audio
, 0, sizeof(*audio
));
682 ps3av_set_hdr(PS3AV_CID_AUDIO_MODE
, sizeof(*audio
), &audio
->send_hdr
);
684 audio
->avport
= (u8
) avport
;
685 audio
->mask
= 0x0FFF; /* XXX set all */
686 audio
->audio_num_of_ch
= ch
;
687 audio
->audio_fs
= fs
;
688 audio
->audio_word_bits
= word_bits
;
689 audio
->audio_format
= format
;
690 audio
->audio_source
= source
;
693 case PS3AV_CMD_AUDIO_NUM_OF_CH_8
:
694 audio
->audio_enable
[3] = 1;
696 case PS3AV_CMD_AUDIO_NUM_OF_CH_6
:
697 audio
->audio_enable
[2] = 1;
698 audio
->audio_enable
[1] = 1;
700 case PS3AV_CMD_AUDIO_NUM_OF_CH_2
:
702 audio
->audio_enable
[0] = 1;
706 for (i
= 0; i
< 4; i
++)
707 audio
->audio_swap
[i
] = PS3AV_CMD_AUDIO_SWAP_0
; /* no swap */
709 /* audio serial input mapping */
710 audio
->audio_map
[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0
;
711 audio
->audio_map
[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1
;
712 audio
->audio_map
[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2
;
713 audio
->audio_map
[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3
;
715 /* audio speaker layout */
716 if (avport
== PS3AV_CMD_AVPORT_HDMI_0
||
717 avport
== PS3AV_CMD_AVPORT_HDMI_1
) {
719 case PS3AV_CMD_AUDIO_NUM_OF_CH_8
:
720 audio
->audio_layout
= PS3AV_CMD_AUDIO_LAYOUT_8CH
;
722 case PS3AV_CMD_AUDIO_NUM_OF_CH_6
:
723 audio
->audio_layout
= PS3AV_CMD_AUDIO_LAYOUT_6CH
;
725 case PS3AV_CMD_AUDIO_NUM_OF_CH_2
:
727 audio
->audio_layout
= PS3AV_CMD_AUDIO_LAYOUT_2CH
;
731 audio
->audio_layout
= PS3AV_CMD_AUDIO_LAYOUT_2CH
;
734 /* audio downmix permission */
735 audio
->audio_downmix
= PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED
;
736 /* audio downmix level shift (0:0dB to 15:15dB) */
737 audio
->audio_downmix_level
= 0; /* 0dB */
740 for (i
= 0; i
< 8; i
++)
741 audio
->audio_cs_info
[i
] = ps3av_mode_cs_info
[i
];
744 case PS3AV_CMD_AUDIO_FS_44K
:
745 audio
->audio_cs_info
[3] &= ~CS_MASK
;
746 audio
->audio_cs_info
[3] |= CS_44
;
748 case PS3AV_CMD_AUDIO_FS_88K
:
749 audio
->audio_cs_info
[3] &= ~CS_MASK
;
750 audio
->audio_cs_info
[3] |= CS_88
;
752 case PS3AV_CMD_AUDIO_FS_96K
:
753 audio
->audio_cs_info
[3] &= ~CS_MASK
;
754 audio
->audio_cs_info
[3] |= CS_96
;
756 case PS3AV_CMD_AUDIO_FS_176K
:
757 audio
->audio_cs_info
[3] &= ~CS_MASK
;
758 audio
->audio_cs_info
[3] |= CS_176
;
760 case PS3AV_CMD_AUDIO_FS_192K
:
761 audio
->audio_cs_info
[3] &= ~CS_MASK
;
762 audio
->audio_cs_info
[3] |= CS_192
;
768 /* pass through setting */
770 (avport
== PS3AV_CMD_AVPORT_SPDIF_0
||
771 avport
== PS3AV_CMD_AVPORT_SPDIF_1
)) {
772 audio
->audio_word_bits
= PS3AV_CMD_AUDIO_WORD_BITS_16
;
773 audio
->audio_source
= PS3AV_CMD_AUDIO_SOURCE_SPDIF
;
774 if (spdif_bitstream
) {
775 audio
->audio_format
= PS3AV_CMD_AUDIO_FORMAT_BITSTREAM
;
776 audio
->audio_cs_info
[0] |= CS_BIT
;
781 int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode
*audio_mode
)
785 res
= ps3av_do_pkt(PS3AV_CID_AUDIO_MODE
, sizeof(*audio_mode
),
786 sizeof(*audio_mode
), &audio_mode
->send_hdr
);
790 res
= get_status(audio_mode
);
792 printk(KERN_ERR
"PS3AV_CID_AUDIO_MODE: failed %x\n", res
);
797 int ps3av_cmd_audio_mute(int num_of_port
, u32
*port
, u32 mute
)
800 struct ps3av_pkt_audio_mute audio_mute
;
802 if (num_of_port
> PS3AV_OPT_PORT_MAX
)
806 memset(&audio_mute
, 0, sizeof(audio_mute
));
807 for (i
= 0; i
< num_of_port
; i
++) {
808 audio_mute
.mute
[i
].avport
= port
[i
];
809 audio_mute
.mute
[i
].mute
= mute
;
812 res
= ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE
,
813 sizeof(audio_mute
.send_hdr
) +
814 sizeof(struct ps3av_audio_mute
) * num_of_port
,
815 sizeof(audio_mute
), &audio_mute
.send_hdr
);
819 res
= get_status(&audio_mute
);
821 printk(KERN_ERR
"PS3AV_CID_AUDIO_MUTE: failed %x\n", res
);
826 int ps3av_cmd_audio_active(int active
, u32 port
)
829 struct ps3av_pkt_audio_active audio_active
;
833 memset(&audio_active
, 0, sizeof(audio_active
));
834 audio_active
.audio_port
= port
;
835 cid
= active
? PS3AV_CID_AUDIO_ACTIVE
: PS3AV_CID_AUDIO_INACTIVE
;
837 res
= ps3av_do_pkt(cid
, sizeof(audio_active
), sizeof(audio_active
),
838 &audio_active
.send_hdr
);
842 res
= get_status(&audio_active
);
844 printk(KERN_ERR
"PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid
,
850 int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param
*avb
, u32 send_len
)
856 res
= ps3av_do_pkt(PS3AV_CID_AVB_PARAM
, send_len
, sizeof(*avb
),
861 res
= get_status(avb
);
863 pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __FUNCTION__
,
870 int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf
*hw_conf
)
874 memset(hw_conf
, 0, sizeof(*hw_conf
));
876 res
= ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF
, sizeof(hw_conf
->send_hdr
),
877 sizeof(*hw_conf
), &hw_conf
->send_hdr
);
881 res
= get_status(hw_conf
);
883 printk(KERN_ERR
"PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res
);
888 int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info
*info
,
893 memset(info
, 0, sizeof(*info
));
894 info
->avport
= avport
;
896 res
= ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO
,
897 sizeof(info
->send_hdr
) + sizeof(info
->avport
) +
898 sizeof(info
->reserved
),
899 sizeof(*info
), &info
->send_hdr
);
903 res
= get_status(info
);
905 printk(KERN_ERR
"PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n",
912 void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf
*hw_conf
)
914 printk("av_h_conf:num of hdmi:%d\n", hw_conf
->num_of_hdmi
);
915 printk("av_h_conf:num of avmulti:%d\n", hw_conf
->num_of_avmulti
);
916 printk("av_h_conf:num of spdif:%d\n", hw_conf
->num_of_spdif
);
919 void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info
*monitor_info
)
921 const struct ps3av_info_monitor
*info
= &monitor_info
->info
;
922 const struct ps3av_info_audio
*audio
= info
->audio
;
925 printk("Monitor Info: size%d\n", monitor_info
->send_hdr
.size
);
927 printk("avport:%02x\n", info
->avport
);
928 printk("monitor_id:");
929 for (i
= 0; i
< 10; i
++)
930 printk("%02x ", info
->monitor_id
[i
]);
931 printk("\nmonitor_type:%02x\n", info
->monitor_type
);
932 printk("monitor_name:");
933 for (i
= 0; i
< 16; i
++)
934 printk("%c", info
->monitor_name
[i
]);
937 printk("\nresolution_60: bits:%08x native:%08x\n",
938 info
->res_60
.res_bits
, info
->res_60
.native
);
939 printk("resolution_50: bits:%08x native:%08x\n",
940 info
->res_50
.res_bits
, info
->res_50
.native
);
941 printk("resolution_other: bits:%08x native:%08x\n",
942 info
->res_other
.res_bits
, info
->res_other
.native
);
943 printk("resolution_vesa: bits:%08x native:%08x\n",
944 info
->res_vesa
.res_bits
, info
->res_vesa
.native
);
947 printk("color space rgb:%02x\n", info
->cs
.rgb
);
948 printk("color space yuv444:%02x\n", info
->cs
.yuv444
);
949 printk("color space yuv422:%02x\n", info
->cs
.yuv422
);
952 printk("color info red:X %04x Y %04x\n",
953 info
->color
.red_x
, info
->color
.red_y
);
954 printk("color info green:X %04x Y %04x\n",
955 info
->color
.green_x
, info
->color
.green_y
);
956 printk("color info blue:X %04x Y %04x\n",
957 info
->color
.blue_x
, info
->color
.blue_y
);
958 printk("color info white:X %04x Y %04x\n",
959 info
->color
.white_x
, info
->color
.white_y
);
960 printk("color info gamma: %08x\n", info
->color
.gamma
);
963 printk("supported_AI:%02x\n", info
->supported_ai
);
964 printk("speaker_info:%02x\n", info
->speaker_info
);
965 printk("num of audio:%02x\n", info
->num_of_audio_block
);
968 for (i
= 0; i
< info
->num_of_audio_block
; i
++) {
969 printk("audio[%d] type:%02x max_ch:%02x fs:%02x sbit:%02x\n",
970 i
, audio
->type
, audio
->max_num_of_ch
, audio
->fs
,
975 #endif /* PS3AV_DEBUG */
977 #define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \
978 | PS3AV_CMD_AV_LAYOUT_44 \
979 | PS3AV_CMD_AV_LAYOUT_48)
981 #define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \
982 | PS3AV_CMD_AV_LAYOUT_88 \
983 | PS3AV_CMD_AV_LAYOUT_96 \
984 | PS3AV_CMD_AV_LAYOUT_176 \
985 | PS3AV_CMD_AV_LAYOUT_192)
987 /************************* vuart ***************************/
989 #define POLLING_INTERVAL 25 /* in msec */
991 int ps3av_vuart_write(struct ps3_vuart_port_device
*dev
, const void *buf
,
994 int error
= ps3_vuart_write(dev
, buf
, size
);
995 return error
? error
: size
;
998 int ps3av_vuart_read(struct ps3_vuart_port_device
*dev
, void *buf
,
999 unsigned long size
, int timeout
)
1004 timeout
= (timeout
+ POLLING_INTERVAL
- 1) / POLLING_INTERVAL
;
1005 while (loopcnt
++ <= timeout
) {
1006 error
= ps3_vuart_read(dev
, buf
, size
);
1009 if (error
!= -EAGAIN
) {
1010 printk(KERN_ERR
"%s: ps3_vuart_read failed %d\n",
1011 __FUNCTION__
, error
);
1014 msleep(POLLING_INTERVAL
);
1016 return -EWOULDBLOCK
;