aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>2007-02-12 03:55:16 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-12 12:48:44 -0500
commit11227fd1922dc5dda691586852cfd220dd383f37 (patch)
treee6631b1e5be83876bbe2c6e5cea3a427ce61a3fa
parent5b8e8ee6c65a34d8aafaeb8e2eaa97e496c2567c (diff)
[PATCH] ps3: AV Settings Driver
Add the PS3 AV Settings Driver. The AV Settings driver is used to control Audio and Video settings. It communicates with the policy manager through the virtual uart. Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> Cc: James Simmons <jsimmons@infradead.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig11
-rw-r--r--drivers/ps3/Makefile1
-rw-r--r--drivers/ps3/ps3av.c974
-rw-r--r--drivers/ps3/ps3av_cmd.c1017
-rw-r--r--include/asm-powerpc/ps3av.h738
5 files changed, 2741 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index de52ec4e9e58..4be3943d1c0d 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -51,4 +51,15 @@ config PS3_VUART
51 including the System Manager and AV Settings. In 51 including the System Manager and AV Settings. In
52 general, all users will say Y. 52 general, all users will say Y.
53 53
54config PS3_PS3AV
55 tristate "PS3 AV settings driver"
56 depends on PPC_PS3
57 select PS3_VUART
58 default y
59 help
60 Include support for the PS3 AV Settings driver.
61
62 This support is required for graphics and sound. In
63 general, all users will say Y or M.
64
54endmenu 65endmenu
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index d547cf50ca9d..96958c03cf61 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1 +1,2 @@
1obj-$(CONFIG_PS3_VUART) += vuart.o 1obj-$(CONFIG_PS3_VUART) += vuart.o
2obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
new file mode 100644
index 000000000000..1926b4d3e1f4
--- /dev/null
+++ b/drivers/ps3/ps3av.c
@@ -0,0 +1,974 @@
1/*
2 * Copyright (C) 2006 Sony Computer Entertainment Inc.
3 * Copyright 2006, 2007 Sony Corporation
4 *
5 * AV backend support for PS3
6 *
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.
10 *
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.
15 *
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.
19 */
20
21#include <linux/module.h>
22#include <linux/delay.h>
23#include <linux/notifier.h>
24#include <linux/reboot.h>
25#include <linux/kernel.h>
26#include <linux/ioctl.h>
27#include <asm/lv1call.h>
28#include <asm/ps3av.h>
29#include <asm/ps3.h>
30
31#include "vuart.h"
32
33#define BUFSIZE 4096 /* vuart buf size */
34#define PS3AV_BUF_SIZE 512 /* max packet size */
35
36static int timeout = 5000; /* in msec ( 5 sec ) */
37module_param(timeout, int, 0644);
38
39static struct ps3av ps3av;
40
41static struct ps3_vuart_port_device ps3av_dev = {
42 .match_id = PS3_MATCH_ID_AV_SETTINGS
43};
44
45/* color space */
46#define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
47#define RGB8 PS3AV_CMD_VIDEO_CS_RGB_8
48/* format */
49#define XRGB PS3AV_CMD_VIDEO_FMT_X8R8G8B8
50/* aspect */
51#define A_N PS3AV_CMD_AV_ASPECT_4_3
52#define A_W PS3AV_CMD_AV_ASPECT_16_9
53static const struct avset_video_mode {
54 u32 cs;
55 u32 fmt;
56 u32 vid;
57 u32 aspect;
58 u32 x;
59 u32 y;
60 u32 interlace;
61 u32 freq;
62} video_mode_table[] = {
63 { 0, }, /* auto */
64 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480, 1, 60},
65 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480, 0, 60},
66 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720, 0, 60},
67 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
68 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
69 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576, 1, 50},
70 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576, 0, 50},
71 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720, 0, 50},
72 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
73 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
74 { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768, 0, 60},
75 { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024, 0, 60},
76 { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200, 0, 60},
77};
78
79/* supported CIDs */
80static u32 cmd_table[] = {
81 /* init */
82 PS3AV_CID_AV_INIT,
83 PS3AV_CID_AV_FIN,
84 PS3AV_CID_VIDEO_INIT,
85 PS3AV_CID_AUDIO_INIT,
86
87 /* set */
88 PS3AV_CID_AV_ENABLE_EVENT,
89 PS3AV_CID_AV_DISABLE_EVENT,
90
91 PS3AV_CID_AV_VIDEO_CS,
92 PS3AV_CID_AV_VIDEO_MUTE,
93 PS3AV_CID_AV_VIDEO_DISABLE_SIG,
94 PS3AV_CID_AV_AUDIO_PARAM,
95 PS3AV_CID_AV_AUDIO_MUTE,
96 PS3AV_CID_AV_HDMI_MODE,
97 PS3AV_CID_AV_TV_MUTE,
98
99 PS3AV_CID_VIDEO_MODE,
100 PS3AV_CID_VIDEO_FORMAT,
101 PS3AV_CID_VIDEO_PITCH,
102
103 PS3AV_CID_AUDIO_MODE,
104 PS3AV_CID_AUDIO_MUTE,
105 PS3AV_CID_AUDIO_ACTIVE,
106 PS3AV_CID_AUDIO_INACTIVE,
107 PS3AV_CID_AVB_PARAM,
108
109 /* get */
110 PS3AV_CID_AV_GET_HW_CONF,
111 PS3AV_CID_AV_GET_MONITOR_INFO,
112
113 /* event */
114 PS3AV_CID_EVENT_UNPLUGGED,
115 PS3AV_CID_EVENT_PLUGGED,
116 PS3AV_CID_EVENT_HDCP_DONE,
117 PS3AV_CID_EVENT_HDCP_FAIL,
118 PS3AV_CID_EVENT_HDCP_AUTH,
119 PS3AV_CID_EVENT_HDCP_ERROR,
120
121 0
122};
123
124#define PS3AV_EVENT_CMD_MASK 0x10000000
125#define PS3AV_EVENT_ID_MASK 0x0000ffff
126#define PS3AV_CID_MASK 0xffffffff
127#define PS3AV_REPLY_BIT 0x80000000
128
129#define ps3av_event_get_port_id(cid) ((cid >> 16) & 0xff)
130
131static u32 *ps3av_search_cmd_table(u32 cid, u32 mask)
132{
133 u32 *table;
134 int i;
135
136 table = cmd_table;
137 for (i = 0;; table++, i++) {
138 if ((*table & mask) == (cid & mask))
139 break;
140 if (*table == 0)
141 return NULL;
142 }
143 return table;
144}
145
146static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
147{
148 u32 *table;
149
150 if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
151 table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
152 if (table)
153 dev_dbg(&ps3av_dev.core,
154 "recv event packet cid:%08x port:0x%x size:%d\n",
155 hdr->cid, ps3av_event_get_port_id(hdr->cid),
156 hdr->size);
157 else
158 printk(KERN_ERR
159 "%s: failed event packet, cid:%08x size:%d\n",
160 __FUNCTION__, hdr->cid, hdr->size);
161 return 1; /* receive event packet */
162 }
163 return 0;
164}
165
166static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
167 struct ps3av_reply_hdr *recv_buf, int write_len,
168 int read_len)
169{
170 int res;
171 u32 cmd;
172 int event;
173
174 if (!ps3av.available)
175 return -ENODEV;
176
177 /* send pkt */
178 res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
179 if (res < 0) {
180 dev_dbg(&ps3av_dev.core,
181 "%s: ps3av_vuart_write() failed (result=%d)\n",
182 __FUNCTION__, res);
183 return res;
184 }
185
186 /* recv pkt */
187 cmd = send_buf->cid;
188 do {
189 /* read header */
190 res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
191 timeout);
192 if (res != PS3AV_HDR_SIZE) {
193 dev_dbg(&ps3av_dev.core,
194 "%s: ps3av_vuart_read() failed (result=%d)\n",
195 __FUNCTION__, res);
196 return res;
197 }
198
199 /* read body */
200 res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
201 recv_buf->size, timeout);
202 if (res < 0) {
203 dev_dbg(&ps3av_dev.core,
204 "%s: ps3av_vuart_read() failed (result=%d)\n",
205 __FUNCTION__, res);
206 return res;
207 }
208 res += PS3AV_HDR_SIZE; /* total len */
209 event = ps3av_parse_event_packet(recv_buf);
210 /* ret > 0 event packet */
211 } while (event);
212
213 if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
214 dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
215 __FUNCTION__, recv_buf->cid);
216 return -EINVAL;
217 }
218
219 return 0;
220}
221
222static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf,
223 const struct ps3av_reply_hdr *recv_buf,
224 int user_buf_size)
225{
226 int return_len;
227
228 if (recv_buf->version != PS3AV_VERSION) {
229 dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n",
230 recv_buf->version);
231 return -EFAULT;
232 }
233 return_len = recv_buf->size + PS3AV_HDR_SIZE;
234 if (return_len > user_buf_size)
235 return_len = user_buf_size;
236 memcpy(cmd_buf, recv_buf, return_len);
237 return 0; /* success */
238}
239
240void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr)
241{
242 hdr->version = PS3AV_VERSION;
243 hdr->size = size - PS3AV_HDR_SIZE;
244 hdr->cid = cid;
245}
246
247int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
248 struct ps3av_send_hdr *buf)
249{
250 int res = 0;
251 union {
252 struct ps3av_reply_hdr reply_hdr;
253 u8 raw[PS3AV_BUF_SIZE];
254 } recv_buf;
255
256 u32 *table;
257
258 BUG_ON(!ps3av.available);
259
260 if (down_interruptible(&ps3av.sem))
261 return -ERESTARTSYS;
262
263 table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
264 BUG_ON(!table);
265 BUG_ON(send_len < PS3AV_HDR_SIZE);
266 BUG_ON(usr_buf_size < send_len);
267 BUG_ON(usr_buf_size > PS3AV_BUF_SIZE);
268
269 /* create header */
270 ps3av_set_hdr(cid, send_len, buf);
271
272 /* send packet via vuart */
273 res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
274 usr_buf_size);
275 if (res < 0) {
276 printk(KERN_ERR
277 "%s: ps3av_send_cmd_pkt() failed (result=%d)\n",
278 __FUNCTION__, res);
279 goto err;
280 }
281
282 /* process reply packet */
283 res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
284 usr_buf_size);
285 if (res < 0) {
286 printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
287 __FUNCTION__, res);
288 goto err;
289 }
290
291 up(&ps3av.sem);
292 return 0;
293
294 err:
295 up(&ps3av.sem);
296 printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res);
297 return res;
298}
299
300static int ps3av_set_av_video_mute(u32 mute)
301{
302 int i, num_of_av_port, res;
303
304 num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
305 ps3av.av_hw_conf.num_of_avmulti;
306 /* video mute on */
307 for (i = 0; i < num_of_av_port; i++) {
308 res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
309 if (res < 0)
310 return -1;
311 }
312
313 return 0;
314}
315
316static int ps3av_set_video_disable_sig(void)
317{
318 int i, num_of_hdmi_port, num_of_av_port, res;
319
320 num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
321 num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
322 ps3av.av_hw_conf.num_of_avmulti;
323
324 /* tv mute */
325 for (i = 0; i < num_of_hdmi_port; i++) {
326 res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
327 PS3AV_CMD_MUTE_ON);
328 if (res < 0)
329 return -1;
330 }
331 msleep(100);
332
333 /* video mute on */
334 for (i = 0; i < num_of_av_port; i++) {
335 res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
336 if (res < 0)
337 return -1;
338 if (i < num_of_hdmi_port) {
339 res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
340 PS3AV_CMD_MUTE_OFF);
341 if (res < 0)
342 return -1;
343 }
344 }
345 msleep(300);
346
347 return 0;
348}
349
350static int ps3av_set_audio_mute(u32 mute)
351{
352 int i, num_of_av_port, num_of_opt_port, res;
353
354 num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
355 ps3av.av_hw_conf.num_of_avmulti;
356 num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
357
358 for (i = 0; i < num_of_av_port; i++) {
359 res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
360 if (res < 0)
361 return -1;
362 }
363 for (i = 0; i < num_of_opt_port; i++) {
364 res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
365 if (res < 0)
366 return -1;
367 }
368
369 return 0;
370}
371
372int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
373{
374 struct ps3av_pkt_avb_param avb_param;
375 int i, num_of_audio, vid, res;
376 struct ps3av_pkt_audio_mode audio_mode;
377 u32 len = 0;
378
379 num_of_audio = ps3av.av_hw_conf.num_of_hdmi +
380 ps3av.av_hw_conf.num_of_avmulti +
381 ps3av.av_hw_conf.num_of_spdif;
382
383 avb_param.num_of_video_pkt = 0;
384 avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */
385 avb_param.num_of_av_video_pkt = 0;
386 avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
387
388 vid = video_mode_table[ps3av.ps3av_mode].vid;
389
390 /* audio mute */
391 ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
392
393 /* audio inactive */
394 res = ps3av_cmd_audio_active(0, ps3av.audio_port);
395 if (res < 0)
396 dev_dbg(&ps3av_dev.core,
397 "ps3av_cmd_audio_active OFF failed\n");
398
399 /* audio_pkt */
400 for (i = 0; i < num_of_audio; i++) {
401 ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
402 word_bits, format, source);
403 if (i < ps3av.av_hw_conf.num_of_hdmi) {
404 /* hdmi only */
405 len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
406 ps3av.av_port[i],
407 &audio_mode, vid);
408 }
409 /* audio_mode pkt should be sent separately */
410 res = ps3av_cmd_audio_mode(&audio_mode);
411 if (res < 0)
412 dev_dbg(&ps3av_dev.core,
413 "ps3av_cmd_audio_mode failed, port:%x\n", i);
414 }
415
416 /* send command using avb pkt */
417 len += offsetof(struct ps3av_pkt_avb_param, buf);
418 res = ps3av_cmd_avb_param(&avb_param, len);
419 if (res < 0)
420 dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
421
422 /* audio mute */
423 ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
424
425 /* audio active */
426 res = ps3av_cmd_audio_active(1, ps3av.audio_port);
427 if (res < 0)
428 dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n");
429
430 return 0;
431}
432
433EXPORT_SYMBOL_GPL(ps3av_set_audio_mode);
434
435static int ps3av_set_videomode(void)
436{
437 /* av video mute */
438 ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
439
440 /* wake up ps3avd to do the actual video mode setting */
441 up(&ps3av.ping);
442
443 return 0;
444}
445
446static void ps3av_set_videomode_cont(u32 id, u32 old_id)
447{
448 struct ps3av_pkt_avb_param avb_param;
449 int i;
450 u32 len = 0, av_video_cs;
451 const struct avset_video_mode *video_mode;
452 int res;
453
454 video_mode = &video_mode_table[id & PS3AV_MODE_MASK];
455
456 avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */
457 avb_param.num_of_audio_pkt = 0;
458 avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
459 ps3av.av_hw_conf.num_of_avmulti;
460 avb_param.num_of_av_audio_pkt = 0;
461
462 /* video signal off */
463 ps3av_set_video_disable_sig();
464
465 /* Retail PS3 product doesn't support this */
466 if (id & PS3AV_MODE_HDCP_OFF) {
467 res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
468 if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
469 dev_dbg(&ps3av_dev.core, "Not supported\n");
470 else if (res)
471 dev_dbg(&ps3av_dev.core,
472 "ps3av_cmd_av_hdmi_mode failed\n");
473 } else if (old_id & PS3AV_MODE_HDCP_OFF) {
474 res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
475 if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
476 dev_dbg(&ps3av_dev.core,
477 "ps3av_cmd_av_hdmi_mode failed\n");
478 }
479
480 /* video_pkt */
481 for (i = 0; i < avb_param.num_of_video_pkt; i++)
482 len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
483 ps3av.head[i], video_mode->vid,
484 video_mode->fmt, id);
485 /* av_video_pkt */
486 for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
487 if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB)
488 av_video_cs = RGB8;
489 else
490 av_video_cs = video_mode->cs;
491#ifndef PS3AV_HDMI_YUV
492 if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
493 ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
494 av_video_cs = RGB8; /* use RGB for HDMI */
495#endif
496 len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
497 ps3av.av_port[i],
498 video_mode->vid, av_video_cs,
499 video_mode->aspect, id);
500 }
501 /* send command using avb pkt */
502 len += offsetof(struct ps3av_pkt_avb_param, buf);
503 res = ps3av_cmd_avb_param(&avb_param, len);
504 if (res == PS3AV_STATUS_NO_SYNC_HEAD)
505 printk(KERN_WARNING
506 "%s: Command failed. Please try your request again. \n",
507 __FUNCTION__);
508 else if (res)
509 dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
510
511 msleep(1500);
512 /* av video mute */
513 ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
514}
515
516static int ps3avd(void *p)
517{
518 struct ps3av *info = p;
519
520 daemonize("ps3avd");
521 while (1) {
522 down(&info->ping);
523 ps3av_set_videomode_cont(info->ps3av_mode,
524 info->ps3av_mode_old);
525 up(&info->pong);
526 }
527 return 0;
528}
529
530static int ps3av_vid2table_id(int vid)
531{
532 int i;
533
534 for (i = 1; i < ARRAY_SIZE(video_mode_table); i++)
535 if (video_mode_table[i].vid == vid)
536 return i;
537 return -1;
538}
539
540static int ps3av_resbit2vid(u32 res_50, u32 res_60)
541{
542 int vid = -1;
543
544 if (res_50 > res_60) { /* if res_50 == res_60, res_60 will be used */
545 if (res_50 & PS3AV_RESBIT_1920x1080P)
546 vid = PS3AV_CMD_VIDEO_VID_1080P_50HZ;
547 else if (res_50 & PS3AV_RESBIT_1920x1080I)
548 vid = PS3AV_CMD_VIDEO_VID_1080I_50HZ;
549 else if (res_50 & PS3AV_RESBIT_1280x720P)
550 vid = PS3AV_CMD_VIDEO_VID_720P_50HZ;
551 else if (res_50 & PS3AV_RESBIT_720x576P)
552 vid = PS3AV_CMD_VIDEO_VID_576P;
553 else
554 vid = -1;
555 } else {
556 if (res_60 & PS3AV_RESBIT_1920x1080P)
557 vid = PS3AV_CMD_VIDEO_VID_1080P_60HZ;
558 else if (res_60 & PS3AV_RESBIT_1920x1080I)
559 vid = PS3AV_CMD_VIDEO_VID_1080I_60HZ;
560 else if (res_60 & PS3AV_RESBIT_1280x720P)
561 vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
562 else if (res_60 & PS3AV_RESBIT_720x480P)
563 vid = PS3AV_CMD_VIDEO_VID_480P;
564 else
565 vid = -1;
566 }
567 return vid;
568}
569
570static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
571{
572 u32 res_50, res_60;
573 int vid = -1;
574
575 if (info->monitor_type != PS3AV_MONITOR_TYPE_HDMI)
576 return -1;
577
578 /* check native resolution */
579 res_50 = info->res_50.native & PS3AV_RES_MASK_50;
580 res_60 = info->res_60.native & PS3AV_RES_MASK_60;
581 if (res_50 || res_60) {
582 vid = ps3av_resbit2vid(res_50, res_60);
583 return vid;
584 }
585
586 /* check resolution */
587 res_50 = info->res_50.res_bits & PS3AV_RES_MASK_50;
588 res_60 = info->res_60.res_bits & PS3AV_RES_MASK_60;
589 if (res_50 || res_60) {
590 vid = ps3av_resbit2vid(res_50, res_60);
591 return vid;
592 }
593
594 if (ps3av.region & PS3AV_REGION_60)
595 vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
596 else
597 vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
598 return vid;
599}
600
601static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
602 int boot)
603{
604 int i, res, vid = -1, dvi = 0, rgb = 0;
605 struct ps3av_pkt_av_get_monitor_info monitor_info;
606 struct ps3av_info_monitor *info;
607
608 /* get vid for hdmi */
609 for (i = 0; i < av_hw_conf->num_of_hdmi; i++) {
610 res = ps3av_cmd_video_get_monitor_info(&monitor_info,
611 PS3AV_CMD_AVPORT_HDMI_0 +
612 i);
613 if (res < 0)
614 return -1;
615
616 ps3av_cmd_av_monitor_info_dump(&monitor_info);
617 info = &monitor_info.info;
618 /* check DVI */
619 if (info->monitor_type == PS3AV_MONITOR_TYPE_DVI) {
620 dvi = PS3AV_MODE_DVI;
621 break;
622 }
623 /* check HDMI */
624 vid = ps3av_hdmi_get_vid(info);
625 if (vid != -1) {
626 /* got valid vid */
627 break;
628 }
629 }
630
631 if (dvi) {
632 /* DVI mode */
633 vid = PS3AV_DEFAULT_DVI_VID;
634 } else if (vid == -1) {
635 /* no HDMI interface or HDMI is off */
636 if (ps3av.region & PS3AV_REGION_60)
637 vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
638 else
639 vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
640 if (ps3av.region & PS3AV_REGION_RGB)
641 rgb = PS3AV_MODE_RGB;
642 } else if (boot) {
643 /* HDMI: using DEFAULT HDMI_VID while booting up */
644 info = &monitor_info.info;
645 if (ps3av.region & PS3AV_REGION_60) {
646 if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
647 vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
648 else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
649 vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
650 else {
651 /* default */
652 vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
653 }
654 } else {
655 if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
656 vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
657 else if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
658 vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
659 else {
660 /* default */
661 vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
662 }
663 }
664 }
665
666 return (ps3av_vid2table_id(vid) | dvi | rgb);
667}
668
669static int ps3av_get_hw_conf(struct ps3av *ps3av)
670{
671 int i, j, k, res;
672
673 /* get av_hw_conf */
674 res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf);
675 if (res < 0)
676 return -1;
677
678 ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf);
679
680 for (i = 0; i < PS3AV_HEAD_MAX; i++)
681 ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i;
682 for (i = 0; i < PS3AV_OPT_PORT_MAX; i++)
683 ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i;
684 for (i = 0; i < ps3av->av_hw_conf.num_of_hdmi; i++)
685 ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i;
686 for (j = 0; j < ps3av->av_hw_conf.num_of_avmulti; j++)
687 ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j;
688 for (k = 0; k < ps3av->av_hw_conf.num_of_spdif; k++)
689 ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k;
690
691 /* set all audio port */
692 ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0
693 | PS3AV_CMD_AUDIO_PORT_HDMI_1
694 | PS3AV_CMD_AUDIO_PORT_AVMULTI_0
695 | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1;
696
697 return 0;
698}
699
700/* set mode using id */
701int ps3av_set_video_mode(u32 id, int boot)
702{
703 int size;
704 u32 option;
705
706 size = ARRAY_SIZE(video_mode_table);
707 if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
708 dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __FUNCTION__,
709 id);
710 return -EINVAL;
711 }
712
713 /* auto mode */
714 option = id & ~PS3AV_MODE_MASK;
715 if ((id & PS3AV_MODE_MASK) == 0) {
716 id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
717 if (id < 1) {
718 printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__,
719 id);
720 return -EINVAL;
721 }
722 id |= option;
723 }
724
725 /* set videomode */
726 down(&ps3av.pong);
727 ps3av.ps3av_mode_old = ps3av.ps3av_mode;
728 ps3av.ps3av_mode = id;
729 if (ps3av_set_videomode())
730 ps3av.ps3av_mode = ps3av.ps3av_mode_old;
731
732 return 0;
733}
734
735EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
736
737int ps3av_set_mode(u32 id, int boot)
738{
739 int res;
740
741 res = ps3av_set_video_mode(id, boot);
742 if (res)
743 return res;
744
745 res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2,
746 PS3AV_CMD_AUDIO_FS_48K,
747 PS3AV_CMD_AUDIO_WORD_BITS_16,
748 PS3AV_CMD_AUDIO_FORMAT_PCM,
749 PS3AV_CMD_AUDIO_SOURCE_SERIAL);
750 if (res)
751 return res;
752
753 return 0;
754}
755
756EXPORT_SYMBOL_GPL(ps3av_set_mode);
757
758int ps3av_get_mode(void)
759{
760 return ps3av.ps3av_mode;
761}
762
763EXPORT_SYMBOL_GPL(ps3av_get_mode);
764
765int ps3av_get_scanmode(int id)
766{
767 int size;
768
769 id = id & PS3AV_MODE_MASK;
770 size = ARRAY_SIZE(video_mode_table);
771 if (id > size - 1 || id < 0) {
772 printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
773 return -EINVAL;
774 }
775 return video_mode_table[id].interlace;
776}
777
778EXPORT_SYMBOL_GPL(ps3av_get_scanmode);
779
780int ps3av_get_refresh_rate(int id)
781{
782 int size;
783
784 id = id & PS3AV_MODE_MASK;
785 size = ARRAY_SIZE(video_mode_table);
786 if (id > size - 1 || id < 0) {
787 printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
788 return -EINVAL;
789 }
790 return video_mode_table[id].freq;
791}
792
793EXPORT_SYMBOL_GPL(ps3av_get_refresh_rate);
794
795/* get resolution by video_mode */
796int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
797{
798 int size;
799
800 id = id & PS3AV_MODE_MASK;
801 size = ARRAY_SIZE(video_mode_table);
802 if (id > size - 1 || id < 0) {
803 printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
804 return -EINVAL;
805 }
806 *xres = video_mode_table[id].x;
807 *yres = video_mode_table[id].y;
808 return 0;
809}
810
811EXPORT_SYMBOL_GPL(ps3av_video_mode2res);
812
813/* mute */
814int ps3av_video_mute(int mute)
815{
816 return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON
817 : PS3AV_CMD_MUTE_OFF);
818}
819
820EXPORT_SYMBOL_GPL(ps3av_video_mute);
821
822int ps3av_audio_mute(int mute)
823{
824 return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
825 : PS3AV_CMD_MUTE_OFF);
826}
827
828EXPORT_SYMBOL_GPL(ps3av_audio_mute);
829
830int ps3av_dev_open(void)
831{
832 int status = 0;
833
834 mutex_lock(&ps3av.mutex);
835 if (!ps3av.open_count++) {
836 status = lv1_gpu_open(0);
837 if (status) {
838 printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
839 __FUNCTION__, status);
840 ps3av.open_count--;
841 }
842 }
843 mutex_unlock(&ps3av.mutex);
844
845 return status;
846}
847
848EXPORT_SYMBOL_GPL(ps3av_dev_open);
849
850int ps3av_dev_close(void)
851{
852 int status = 0;
853
854 mutex_lock(&ps3av.mutex);
855 if (ps3av.open_count <= 0) {
856 printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__);
857 status = -1;
858 } else if (!--ps3av.open_count) {
859 status = lv1_gpu_close();
860 if (status)
861 printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
862 __FUNCTION__, status);
863 }
864 mutex_unlock(&ps3av.mutex);
865
866 return status;
867}
868
869EXPORT_SYMBOL_GPL(ps3av_dev_close);
870
871static int ps3av_probe(struct ps3_vuart_port_device *dev)
872{
873 int res;
874 u32 id;
875
876 dev_dbg(&ps3av_dev.core, "init ...\n");
877 dev_dbg(&ps3av_dev.core, " timeout=%d\n", timeout);
878
879 memset(&ps3av, 0, sizeof(ps3av));
880
881 init_MUTEX(&ps3av.sem);
882 init_MUTEX_LOCKED(&ps3av.ping);
883 init_MUTEX(&ps3av.pong);
884 mutex_init(&ps3av.mutex);
885 ps3av.ps3av_mode = 0;
886 ps3av.dev = dev;
887 kernel_thread(ps3avd, &ps3av, CLONE_KERNEL);
888
889 ps3av.available = 1;
890 switch (ps3_os_area_get_av_multi_out()) {
891 case PS3_PARAM_AV_MULTI_OUT_NTSC:
892 ps3av.region = PS3AV_REGION_60;
893 break;
894 case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
895 case PS3_PARAM_AV_MULTI_OUT_SECAM:
896 ps3av.region = PS3AV_REGION_50;
897 break;
898 case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
899 ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
900 break;
901 default:
902 ps3av.region = PS3AV_REGION_60;
903 break;
904 }
905
906 /* init avsetting modules */
907 res = ps3av_cmd_init();
908 if (res < 0)
909 printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__,
910 res);
911
912 ps3av_get_hw_conf(&ps3av);
913 id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
914 mutex_lock(&ps3av.mutex);
915 ps3av.ps3av_mode = id;
916 mutex_unlock(&ps3av.mutex);
917
918 dev_dbg(&ps3av_dev.core, "init...done\n");
919
920 return 0;
921}
922
923static int ps3av_remove(struct ps3_vuart_port_device *dev)
924{
925 if (ps3av.available) {
926 ps3av_cmd_fin();
927 ps3av.available = 0;
928 }
929
930 return 0;
931}
932
933static void ps3av_shutdown(struct ps3_vuart_port_device *dev)
934{
935 ps3av_remove(dev);
936}
937
938static struct ps3_vuart_port_driver ps3av_driver = {
939 .match_id = PS3_MATCH_ID_AV_SETTINGS,
940 .core = {
941 .name = "ps3_av",
942 },
943 .probe = ps3av_probe,
944 .remove = ps3av_remove,
945 .shutdown = ps3av_shutdown,
946};
947
948static int ps3av_module_init(void)
949{
950 int error = ps3_vuart_port_driver_register(&ps3av_driver);
951 if (error) {
952 printk(KERN_ERR
953 "%s: ps3_vuart_port_driver_register failed %d\n",
954 __FUNCTION__, error);
955 return error;
956 }
957
958 error = ps3_vuart_port_device_register(&ps3av_dev);
959 if (error)
960 printk(KERN_ERR
961 "%s: ps3_vuart_port_device_register failed %d\n",
962 __FUNCTION__, error);
963
964 return error;
965}
966
967static void __exit ps3av_module_exit(void)
968{
969 device_unregister(&ps3av_dev.core);
970 ps3_vuart_port_driver_unregister(&ps3av_driver);
971}
972
973subsys_initcall(ps3av_module_init);
974module_exit(ps3av_module_exit);
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
new file mode 100644
index 000000000000..b3d1bc40a1b8
--- /dev/null
+++ b/drivers/ps3/ps3av_cmd.c
@@ -0,0 +1,1017 @@
1/*
2 * Copyright (C) 2006 Sony Computer Entertainment Inc.
3 * Copyright 2006, 2007 Sony Corporation
4 *
5 * AV backend support for PS3
6 *
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.
10 *
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.
15 *
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.
19 */
20
21#include <linux/module.h>
22#include <linux/kernel.h>
23#include <linux/delay.h>
24#include <asm/ps3av.h>
25#include <asm/ps3.h>
26
27#include "vuart.h"
28
29static const struct video_fmt {
30 u32 format;
31 u32 order;
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 },
35};
36
37static const struct {
38 int cs;
39 u32 av;
40 u32 bl;
41} ps3av_cs_video2av_table[] = {
42 {
43 .cs = PS3AV_CMD_VIDEO_CS_RGB_8,
44 .av = PS3AV_CMD_AV_CS_RGB_8,
45 .bl = PS3AV_CMD_AV_CS_8
46 }, {
47 .cs = PS3AV_CMD_VIDEO_CS_RGB_10,
48 .av = PS3AV_CMD_AV_CS_RGB_8,
49 .bl = PS3AV_CMD_AV_CS_8
50 }, {
51 .cs = PS3AV_CMD_VIDEO_CS_RGB_12,
52 .av = PS3AV_CMD_AV_CS_RGB_8,
53 .bl = PS3AV_CMD_AV_CS_8
54 }, {
55 .cs = PS3AV_CMD_VIDEO_CS_YUV444_8,
56 .av = PS3AV_CMD_AV_CS_YUV444_8,
57 .bl = PS3AV_CMD_AV_CS_8
58 }, {
59 .cs = PS3AV_CMD_VIDEO_CS_YUV444_10,
60 .av = PS3AV_CMD_AV_CS_YUV444_8,
61 .bl = PS3AV_CMD_AV_CS_10
62 }, {
63 .cs = PS3AV_CMD_VIDEO_CS_YUV444_12,
64 .av = PS3AV_CMD_AV_CS_YUV444_8,
65 .bl = PS3AV_CMD_AV_CS_10
66 }, {
67 .cs = PS3AV_CMD_VIDEO_CS_YUV422_8,
68 .av = PS3AV_CMD_AV_CS_YUV422_8,
69 .bl = PS3AV_CMD_AV_CS_10
70 }, {
71 .cs = PS3AV_CMD_VIDEO_CS_YUV422_10,
72 .av = PS3AV_CMD_AV_CS_YUV422_8,
73 .bl = PS3AV_CMD_AV_CS_10
74 }, {
75 .cs = PS3AV_CMD_VIDEO_CS_YUV422_12,
76 .av = PS3AV_CMD_AV_CS_YUV422_8,
77 .bl = PS3AV_CMD_AV_CS_12
78 }, {
79 .cs = PS3AV_CMD_VIDEO_CS_XVYCC_8,
80 .av = PS3AV_CMD_AV_CS_XVYCC_8,
81 .bl = PS3AV_CMD_AV_CS_12
82 }, {
83 .cs = PS3AV_CMD_VIDEO_CS_XVYCC_10,
84 .av = PS3AV_CMD_AV_CS_XVYCC_8,
85 .bl = PS3AV_CMD_AV_CS_12
86 }, {
87 .cs = PS3AV_CMD_VIDEO_CS_XVYCC_12,
88 .av = PS3AV_CMD_AV_CS_XVYCC_8,
89 .bl = PS3AV_CMD_AV_CS_12
90 }
91};
92
93static u32 ps3av_cs_video2av(int cs)
94{
95 unsigned int i;
96
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;
100
101 return PS3AV_CMD_AV_CS_RGB_8;
102}
103
104static u32 ps3av_cs_video2av_bitlen(int cs)
105{
106 unsigned int i;
107
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;
111
112 return PS3AV_CMD_AV_CS_8;
113}
114
115static const struct {
116 int vid;
117 u32 av;
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 }
132};
133
134static u32 ps3av_vid_video2av(int vid)
135{
136 unsigned int i;
137
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;
141
142 return PS3AV_CMD_AV_VID_480P;
143}
144
145int ps3av_cmd_init(void)
146{
147 int res;
148 struct ps3av_pkt_av_init av_init;
149 struct ps3av_pkt_video_init video_init;
150 struct ps3av_pkt_audio_init audio_init;
151
152 /* video init */
153 memset(&video_init, 0, sizeof(video_init));
154
155 res = ps3av_do_pkt(PS3AV_CID_VIDEO_INIT, sizeof(video_init.send_hdr),
156 sizeof(video_init), &video_init.send_hdr);
157 if (res < 0)
158 return res;
159
160 res = get_status(&video_init);
161 if (res) {
162 printk(KERN_ERR "PS3AV_CID_VIDEO_INIT: failed %x\n", res);
163 return res;
164 }
165
166 /* audio init */
167 memset(&audio_init, 0, sizeof(audio_init));
168
169 res = ps3av_do_pkt(PS3AV_CID_AUDIO_INIT, sizeof(audio_init.send_hdr),
170 sizeof(audio_init), &audio_init.send_hdr);
171 if (res < 0)
172 return res;
173
174 res = get_status(&audio_init);
175 if (res) {
176 printk(KERN_ERR "PS3AV_CID_AUDIO_INIT: failed %x\n", res);
177 return res;
178 }
179
180 /* av init */
181 memset(&av_init, 0, sizeof(av_init));
182 av_init.event_bit = 0;
183
184 res = ps3av_do_pkt(PS3AV_CID_AV_INIT, sizeof(av_init), sizeof(av_init),
185 &av_init.send_hdr);
186 if (res < 0)
187 return res;
188
189 res = get_status(&av_init);
190 if (res)
191 printk(KERN_ERR "PS3AV_CID_AV_INIT: failed %x\n", res);
192
193 return res;
194}
195
196int ps3av_cmd_fin(void)
197{
198 int res;
199 struct ps3av_pkt_av_fin av_fin;
200
201 memset(&av_fin, 0, sizeof(av_fin));
202
203 res = ps3av_do_pkt(PS3AV_CID_AV_FIN, sizeof(av_fin.send_hdr),
204 sizeof(av_fin), &av_fin.send_hdr);
205 if (res < 0)
206 return res;
207
208 res = get_status(&av_fin);
209 if (res)
210 printk(KERN_ERR "PS3AV_CID_AV_FIN: failed %x\n", res);
211
212 return res;
213}
214
215int ps3av_cmd_av_video_mute(int num_of_port, u32 *port, u32 mute)
216{
217 int i, send_len, res;
218 struct ps3av_pkt_av_video_mute av_video_mute;
219
220 if (num_of_port > PS3AV_MUTE_PORT_MAX)
221 return -EINVAL;
222
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;
227 }
228
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);
233 if (res < 0)
234 return res;
235
236 res = get_status(&av_video_mute);
237 if (res)
238 printk(KERN_ERR "PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res);
239
240 return res;
241}
242
243int ps3av_cmd_av_video_disable_sig(u32 port)
244{
245 int res;
246 struct ps3av_pkt_av_video_disable_sig av_video_sig;
247
248 memset(&av_video_sig, 0, sizeof(av_video_sig));
249 av_video_sig.avport = port;
250
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);
254 if (res < 0)
255 return res;
256
257 res = get_status(&av_video_sig);
258 if (res)
259 printk(KERN_ERR
260 "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n",
261 res, port);
262
263 return res;
264}
265
266int ps3av_cmd_av_tv_mute(u32 avport, u32 mute)
267{
268 int res;
269 struct ps3av_pkt_av_tv_mute tv_mute;
270
271 memset(&tv_mute, 0, sizeof(tv_mute));
272 tv_mute.avport = avport;
273 tv_mute.mute = mute;
274
275 res = ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE, sizeof(tv_mute),
276 sizeof(tv_mute), &tv_mute.send_hdr);
277 if (res < 0)
278 return res;
279
280 res = get_status(&tv_mute);
281 if (res)
282 printk(KERN_ERR "PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n",
283 res, avport);
284
285 return res;
286}
287
288int ps3av_cmd_enable_event(void)
289{
290 int res;
291 struct ps3av_pkt_av_event av_event;
292
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;
296
297 res = ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT, sizeof(av_event),
298 sizeof(av_event), &av_event.send_hdr);
299 if (res < 0)
300 return res;
301
302 res = get_status(&av_event);
303 if (res)
304 printk(KERN_ERR "PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res);
305
306 return res;
307}
308
309int ps3av_cmd_av_hdmi_mode(u8 mode)
310{
311 int res;
312 struct ps3av_pkt_av_hdmi_mode hdmi_mode;
313
314 memset(&hdmi_mode, 0, sizeof(hdmi_mode));
315 hdmi_mode.mode = mode;
316
317 res = ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE, sizeof(hdmi_mode),
318 sizeof(hdmi_mode), &hdmi_mode.send_hdr);
319 if (res < 0)
320 return res;
321
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);
325
326 return res;
327}
328
329u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out,
330 int aspect, u32 id)
331{
332 struct ps3av_pkt_av_video_cs *av_video_cs;
333
334 av_video_cs = (struct ps3av_pkt_av_video_cs *)p;
335 if (video_vid == -1)
336 video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
337 if (cs_out == -1)
338 cs_out = PS3AV_CMD_VIDEO_CS_YUV444_8;
339 if (aspect == -1)
340 aspect = 0;
341
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;
356 } else {
357 /* default off */
358 av_video_cs->dither = PS3AV_CMD_AV_DITHER_OFF;
359 }
360
361 return sizeof(*av_video_cs);
362}
363
364u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt,
365 u32 id)
366{
367 struct ps3av_pkt_video_mode *video_mode;
368 u32 x, y;
369
370 video_mode = (struct ps3av_pkt_video_mode *)p;
371 if (video_vid == -1)
372 video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
373 if (video_fmt == -1)
374 video_fmt = PS3AV_CMD_VIDEO_FMT_X8R8G8B8;
375
376 if (ps3av_video_mode2res(id, &x, &y))
377 return 0;
378
379 /* video mode */
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;
387 else
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;
395
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);
401}
402
403int ps3av_cmd_video_format_black(u32 head, u32 video_fmt, u32 mute)
404{
405 int res;
406 struct ps3av_pkt_video_format video_format;
407
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;
412 else
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;
416
417 res = ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT, sizeof(video_format),
418 sizeof(video_format), &video_format.send_hdr);
419 if (res < 0)
420 return res;
421
422 res = get_status(&video_format);
423 if (res)
424 printk(KERN_ERR "PS3AV_CID_VIDEO_FORMAT: failed %x\n", res);
425
426 return res;
427}
428
429
430int ps3av_cmd_av_audio_mute(int num_of_port, u32 *port, u32 mute)
431{
432 int i, res;
433 struct ps3av_pkt_av_audio_mute av_audio_mute;
434
435 if (num_of_port > PS3AV_MUTE_PORT_MAX)
436 return -EINVAL;
437
438 /* audio mute */
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;
443 }
444
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);
449 if (res < 0)
450 return res;
451
452 res = get_status(&av_audio_mute);
453 if (res)
454 printk(KERN_ERR "PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res);
455
456 return res;
457}
458
459static const struct {
460 u32 fs;
461 u8 mclk;
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 }
469};
470
471static u8 ps3av_cnv_mclk(u32 fs)
472{
473 unsigned int i;
474
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;
478
479 printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
480 return 0;
481}
482
483#define BASE PS3AV_CMD_AUDIO_FS_44K
484
485static 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 }
493};
494
495static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
496{
497 u32 av_vid, ns_val;
498 u8 *p = ns;
499 int d;
500
501 d = ns_val = 0;
502 av_vid = ps3av_vid_video2av(video_vid);
503 switch (av_vid) {
504 case PS3AV_CMD_AV_VID_480I:
505 case PS3AV_CMD_AV_VID_576I:
506 d = 0;
507 break;
508 case PS3AV_CMD_AV_VID_480P:
509 case PS3AV_CMD_AV_VID_576P:
510 d = 1;
511 break;
512 case PS3AV_CMD_AV_VID_1080I_60HZ:
513 case PS3AV_CMD_AV_VID_1080I_50HZ:
514 d = 2;
515 break;
516 case PS3AV_CMD_AV_VID_720P_60HZ:
517 case PS3AV_CMD_AV_VID_720P_50HZ:
518 d = 3;
519 break;
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:
525 d = 4;
526 break;
527 default:
528 printk(KERN_ERR "%s failed, vid:%x\n", __FUNCTION__,
529 video_vid);
530 break;
531 }
532
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);
535 else
536 ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d];
537
538 *p++ = ns_val & 0x000000FF;
539 *p++ = (ns_val & 0x0000FF00) >> 8;
540 *p = (ns_val & 0x00FF0000) >> 16;
541}
542
543#undef BASE
544
545static u8 ps3av_cnv_enable(u32 source, u8 *enable)
546{
547 u8 *p, ret = 0;
548
549 if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) {
550 ret = 0x03;
551 } else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) {
552 p = enable;
553 ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) |
554 0x01;
555 } else
556 printk(KERN_ERR "%s failed, source:%x\n", __FUNCTION__,
557 source);
558 return ret;
559}
560
561static u8 ps3av_cnv_fifomap(u8 *map)
562{
563 u8 *p, ret = 0;
564
565 p = map;
566 ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6);
567 return ret;
568}
569
570static u8 ps3av_cnv_inputlen(u32 word_bits)
571{
572 u8 ret = 0;
573
574 switch (word_bits) {
575 case PS3AV_CMD_AUDIO_WORD_BITS_16:
576 ret = PS3AV_CMD_AV_INPUTLEN_16;
577 break;
578 case PS3AV_CMD_AUDIO_WORD_BITS_20:
579 ret = PS3AV_CMD_AV_INPUTLEN_20;
580 break;
581 case PS3AV_CMD_AUDIO_WORD_BITS_24:
582 ret = PS3AV_CMD_AV_INPUTLEN_24;
583 break;
584 default:
585 printk(KERN_ERR "%s failed, word_bits:%x\n", __FUNCTION__,
586 word_bits);
587 break;
588 }
589 return ret;
590}
591
592static u8 ps3av_cnv_layout(u32 num_of_ch)
593{
594 if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) {
595 printk(KERN_ERR "%s failed, num_of_ch:%x\n", __FUNCTION__,
596 num_of_ch);
597 return 0;
598 }
599
600 return num_of_ch == PS3AV_CMD_AUDIO_NUM_OF_CH_2 ? 0x0 : 0x1;
601}
602
603static void ps3av_cnv_info(struct ps3av_audio_info_frame *info,
604 const struct ps3av_pkt_audio_mode *mode)
605{
606 info->pb1.cc = mode->audio_num_of_ch + 1; /* CH2:0x01 --- CH8:0x07 */
607 info->pb1.ct = 0;
608 info->pb2.sf = 0;
609 info->pb2.ss = 0;
610
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;
615}
616
617static void ps3av_cnv_chstat(u8 *chstat, u8 *cs_info)
618{
619 memcpy(chstat, cs_info, 5);
620}
621
622u32 ps3av_cmd_set_av_audio_param(void *p, u32 port,
623 const struct ps3av_pkt_audio_mode *audio_mode,
624 u32 video_vid)
625{
626 struct ps3av_pkt_av_audio_param *param;
627
628 param = (struct ps3av_pkt_av_audio_param *)p;
629
630 memset(param, 0, sizeof(*param));
631 ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM, sizeof(*param),
632 &param->send_hdr);
633
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(&param->info, audio_mode);
645 ps3av_cnv_chstat(param->chstat, audio_mode->audio_cs_info);
646
647 return sizeof(*param);
648}
649
650/* default cs val */
651static const u8 ps3av_mode_cs_info[] = {
652 0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
653};
654
655#define CS_44 0x00
656#define CS_48 0x02
657#define CS_88 0x08
658#define CS_96 0x0a
659#define CS_176 0x0c
660#define CS_192 0x0e
661#define CS_MASK 0x0f
662#define CS_BIT 0x40
663
664void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
665 u32 ch, u32 fs, u32 word_bits, u32 format,
666 u32 source)
667{
668 int spdif_through, spdif_bitstream;
669 int i;
670
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;
677 }
678 spdif_through = spdif_bitstream = 0; /* XXX not supported */
679
680 /* audio mode */
681 memset(audio, 0, sizeof(*audio));
682 ps3av_set_hdr(PS3AV_CID_AUDIO_MODE, sizeof(*audio), &audio->send_hdr);
683
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;
691
692 switch (ch) {
693 case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
694 audio->audio_enable[3] = 1;
695 /* fall through */
696 case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
697 audio->audio_enable[2] = 1;
698 audio->audio_enable[1] = 1;
699 /* fall through */
700 case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
701 default:
702 audio->audio_enable[0] = 1;
703 }
704
705 /* audio swap L/R */
706 for (i = 0; i < 4; i++)
707 audio->audio_swap[i] = PS3AV_CMD_AUDIO_SWAP_0; /* no swap */
708
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;
714
715 /* audio speaker layout */
716 if (avport == PS3AV_CMD_AVPORT_HDMI_0 ||
717 avport == PS3AV_CMD_AVPORT_HDMI_1) {
718 switch (ch) {
719 case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
720 audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_8CH;
721 break;
722 case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
723 audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_6CH;
724 break;
725 case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
726 default:
727 audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
728 break;
729 }
730 } else {
731 audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
732 }
733
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 */
738
739 /* set ch status */
740 for (i = 0; i < 8; i++)
741 audio->audio_cs_info[i] = ps3av_mode_cs_info[i];
742
743 switch (fs) {
744 case PS3AV_CMD_AUDIO_FS_44K:
745 audio->audio_cs_info[3] &= ~CS_MASK;
746 audio->audio_cs_info[3] |= CS_44;
747 break;
748 case PS3AV_CMD_AUDIO_FS_88K:
749 audio->audio_cs_info[3] &= ~CS_MASK;
750 audio->audio_cs_info[3] |= CS_88;
751 break;
752 case PS3AV_CMD_AUDIO_FS_96K:
753 audio->audio_cs_info[3] &= ~CS_MASK;
754 audio->audio_cs_info[3] |= CS_96;
755 break;
756 case PS3AV_CMD_AUDIO_FS_176K:
757 audio->audio_cs_info[3] &= ~CS_MASK;
758 audio->audio_cs_info[3] |= CS_176;
759 break;
760 case PS3AV_CMD_AUDIO_FS_192K:
761 audio->audio_cs_info[3] &= ~CS_MASK;
762 audio->audio_cs_info[3] |= CS_192;
763 break;
764 default:
765 break;
766 }
767
768 /* pass through setting */
769 if (spdif_through &&
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;
777 }
778 }
779}
780
781int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *audio_mode)
782{
783 int res;
784
785 res = ps3av_do_pkt(PS3AV_CID_AUDIO_MODE, sizeof(*audio_mode),
786 sizeof(*audio_mode), &audio_mode->send_hdr);
787 if (res < 0)
788 return res;
789
790 res = get_status(audio_mode);
791 if (res)
792 printk(KERN_ERR "PS3AV_CID_AUDIO_MODE: failed %x\n", res);
793
794 return res;
795}
796
797int ps3av_cmd_audio_mute(int num_of_port, u32 *port, u32 mute)
798{
799 int i, res;
800 struct ps3av_pkt_audio_mute audio_mute;
801
802 if (num_of_port > PS3AV_OPT_PORT_MAX)
803 return -EINVAL;
804
805 /* audio mute */
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;
810 }
811
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);
816 if (res < 0)
817 return res;
818
819 res = get_status(&audio_mute);
820 if (res)
821 printk(KERN_ERR "PS3AV_CID_AUDIO_MUTE: failed %x\n", res);
822
823 return res;
824}
825
826int ps3av_cmd_audio_active(int active, u32 port)
827{
828 int res;
829 struct ps3av_pkt_audio_active audio_active;
830 u32 cid;
831
832 /* 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;
836
837 res = ps3av_do_pkt(cid, sizeof(audio_active), sizeof(audio_active),
838 &audio_active.send_hdr);
839 if (res < 0)
840 return res;
841
842 res = get_status(&audio_active);
843 if (res)
844 printk(KERN_ERR "PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid,
845 res);
846
847 return res;
848}
849
850int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
851{
852 int res;
853
854 /* avb packet */
855
856 res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
857 &avb->send_hdr);
858 if (res < 0)
859 goto out;
860
861 res = get_status(avb);
862 if (res)
863 pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __FUNCTION__,
864 res);
865
866 out:
867 return res;
868}
869
870int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *hw_conf)
871{
872 int res;
873
874 memset(hw_conf, 0, sizeof(*hw_conf));
875
876 res = ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF, sizeof(hw_conf->send_hdr),
877 sizeof(*hw_conf), &hw_conf->send_hdr);
878 if (res < 0)
879 return res;
880
881 res = get_status(hw_conf);
882 if (res)
883 printk(KERN_ERR "PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res);
884
885 return res;
886}
887
888int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info,
889 u32 avport)
890{
891 int res;
892
893 memset(info, 0, sizeof(*info));
894 info->avport = avport;
895
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);
900 if (res < 0)
901 return res;
902
903 res = get_status(info);
904 if (res)
905 printk(KERN_ERR "PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n",
906 res);
907
908 return res;
909}
910
911#ifdef PS3AV_DEBUG
912void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf)
913{
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);
917}
918
919void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
920{
921 const struct ps3av_info_monitor *info = &monitor_info->info;
922 const struct ps3av_info_audio *audio = info->audio;
923 int i;
924
925 printk("Monitor Info: size%d\n", monitor_info->send_hdr.size);
926
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]);
935
936 /* resolution */
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);
945
946 /* color space */
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);
950
951 /* color info */
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);
961
962 /* other info */
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);
966
967 /* 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,
971 audio->sbit);
972 audio++;
973 }
974}
975#endif /* PS3AV_DEBUG */
976
977#define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \
978 | PS3AV_CMD_AV_LAYOUT_44 \
979 | PS3AV_CMD_AV_LAYOUT_48)
980
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)
986
987/************************* vuart ***************************/
988
989#define POLLING_INTERVAL 25 /* in msec */
990
991int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
992 unsigned long size)
993{
994 int error = ps3_vuart_write(dev, buf, size);
995 return error ? error : size;
996}
997
998int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
999 unsigned long size, int timeout)
1000{
1001 int error;
1002 int loopcnt = 0;
1003
1004 timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
1005 while (loopcnt++ <= timeout) {
1006 error = ps3_vuart_read(dev, buf, size);
1007 if (!error)
1008 return size;
1009 if (error != -EAGAIN) {
1010 printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
1011 __FUNCTION__, error);
1012 return error;
1013 }
1014 msleep(POLLING_INTERVAL);
1015 }
1016 return -EWOULDBLOCK;
1017}
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
new file mode 100644
index 000000000000..43e90ea96136
--- /dev/null
+++ b/include/asm-powerpc/ps3av.h
@@ -0,0 +1,738 @@
1/*
2 * Copyright (C) 2006 Sony Computer Entertainment Inc.
3 * Copyright 2006, 2007 Sony Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18#ifndef _ASM_POWERPC_PS3AV_H_
19#define _ASM_POWERPC_PS3AV_H_
20
21#include <linux/mutex.h>
22
23/** command for ioctl() **/
24#define PS3AV_VERSION 0x205 /* version of ps3av command */
25
26#define PS3AV_CID_AV_INIT 0x00000001
27#define PS3AV_CID_AV_FIN 0x00000002
28#define PS3AV_CID_AV_GET_HW_CONF 0x00000003
29#define PS3AV_CID_AV_GET_MONITOR_INFO 0x00000004
30#define PS3AV_CID_AV_ENABLE_EVENT 0x00000006
31#define PS3AV_CID_AV_DISABLE_EVENT 0x00000007
32#define PS3AV_CID_AV_TV_MUTE 0x0000000a
33
34#define PS3AV_CID_AV_VIDEO_CS 0x00010001
35#define PS3AV_CID_AV_VIDEO_MUTE 0x00010002
36#define PS3AV_CID_AV_VIDEO_DISABLE_SIG 0x00010003
37#define PS3AV_CID_AV_AUDIO_PARAM 0x00020001
38#define PS3AV_CID_AV_AUDIO_MUTE 0x00020002
39#define PS3AV_CID_AV_HDMI_MODE 0x00040001
40
41#define PS3AV_CID_VIDEO_INIT 0x01000001
42#define PS3AV_CID_VIDEO_MODE 0x01000002
43#define PS3AV_CID_VIDEO_FORMAT 0x01000004
44#define PS3AV_CID_VIDEO_PITCH 0x01000005
45
46#define PS3AV_CID_AUDIO_INIT 0x02000001
47#define PS3AV_CID_AUDIO_MODE 0x02000002
48#define PS3AV_CID_AUDIO_MUTE 0x02000003
49#define PS3AV_CID_AUDIO_ACTIVE 0x02000004
50#define PS3AV_CID_AUDIO_INACTIVE 0x02000005
51#define PS3AV_CID_AUDIO_SPDIF_BIT 0x02000006
52#define PS3AV_CID_AUDIO_CTRL 0x02000007
53
54#define PS3AV_CID_EVENT_UNPLUGGED 0x10000001
55#define PS3AV_CID_EVENT_PLUGGED 0x10000002
56#define PS3AV_CID_EVENT_HDCP_DONE 0x10000003
57#define PS3AV_CID_EVENT_HDCP_FAIL 0x10000004
58#define PS3AV_CID_EVENT_HDCP_AUTH 0x10000005
59#define PS3AV_CID_EVENT_HDCP_ERROR 0x10000006
60
61#define PS3AV_CID_AVB_PARAM 0x04000001
62
63/* max backend ports */
64#define PS3AV_HDMI_MAX 2 /* HDMI_0 HDMI_1 */
65#define PS3AV_AVMULTI_MAX 1 /* AVMULTI_0 */
66#define PS3AV_AV_PORT_MAX (PS3AV_HDMI_MAX + PS3AV_AVMULTI_MAX)
67#define PS3AV_OPT_PORT_MAX 1 /* SPDIF0 */
68#define PS3AV_HEAD_MAX 2 /* HEAD_A HEAD_B */
69
70/* num of pkt for PS3AV_CID_AVB_PARAM */
71#define PS3AV_AVB_NUM_VIDEO PS3AV_HEAD_MAX
72#define PS3AV_AVB_NUM_AUDIO 0 /* not supported */
73#define PS3AV_AVB_NUM_AV_VIDEO PS3AV_AV_PORT_MAX
74#define PS3AV_AVB_NUM_AV_AUDIO PS3AV_HDMI_MAX
75
76#define PS3AV_MUTE_PORT_MAX 1 /* num of ports in mute pkt */
77
78/* event_bit */
79#define PS3AV_CMD_EVENT_BIT_UNPLUGGED (1 << 0)
80#define PS3AV_CMD_EVENT_BIT_PLUGGED (1 << 1)
81#define PS3AV_CMD_EVENT_BIT_HDCP_DONE (1 << 2)
82#define PS3AV_CMD_EVENT_BIT_HDCP_FAIL (1 << 3)
83#define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH (1 << 4)
84#define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY (1 << 5)
85
86/* common params */
87/* mute */
88#define PS3AV_CMD_MUTE_OFF 0x0000
89#define PS3AV_CMD_MUTE_ON 0x0001
90/* avport */
91#define PS3AV_CMD_AVPORT_HDMI_0 0x0000
92#define PS3AV_CMD_AVPORT_HDMI_1 0x0001
93#define PS3AV_CMD_AVPORT_AVMULTI_0 0x0010
94#define PS3AV_CMD_AVPORT_SPDIF_0 0x0020
95#define PS3AV_CMD_AVPORT_SPDIF_1 0x0021
96
97/* for av backend */
98/* av_mclk */
99#define PS3AV_CMD_AV_MCLK_128 0x0000
100#define PS3AV_CMD_AV_MCLK_256 0x0001
101#define PS3AV_CMD_AV_MCLK_512 0x0003
102/* av_inputlen */
103#define PS3AV_CMD_AV_INPUTLEN_16 0x02
104#define PS3AV_CMD_AV_INPUTLEN_20 0x0a
105#define PS3AV_CMD_AV_INPUTLEN_24 0x0b
106/* alayout */
107#define PS3AV_CMD_AV_LAYOUT_32 (1 << 0)
108#define PS3AV_CMD_AV_LAYOUT_44 (1 << 1)
109#define PS3AV_CMD_AV_LAYOUT_48 (1 << 2)
110#define PS3AV_CMD_AV_LAYOUT_88 (1 << 3)
111#define PS3AV_CMD_AV_LAYOUT_96 (1 << 4)
112#define PS3AV_CMD_AV_LAYOUT_176 (1 << 5)
113#define PS3AV_CMD_AV_LAYOUT_192 (1 << 6)
114/* hdmi_mode */
115#define PS3AV_CMD_AV_HDMI_MODE_NORMAL 0xff
116#define PS3AV_CMD_AV_HDMI_HDCP_OFF 0x01
117#define PS3AV_CMD_AV_HDMI_EDID_PASS 0x80
118#define PS3AV_CMD_AV_HDMI_DVI 0x40
119
120/* for video module */
121/* video_head */
122#define PS3AV_CMD_VIDEO_HEAD_A 0x0000
123#define PS3AV_CMD_VIDEO_HEAD_B 0x0001
124/* video_cs_out video_cs_in */
125#define PS3AV_CMD_VIDEO_CS_NONE 0x0000
126#define PS3AV_CMD_VIDEO_CS_RGB_8 0x0001
127#define PS3AV_CMD_VIDEO_CS_YUV444_8 0x0002
128#define PS3AV_CMD_VIDEO_CS_YUV422_8 0x0003
129#define PS3AV_CMD_VIDEO_CS_XVYCC_8 0x0004
130#define PS3AV_CMD_VIDEO_CS_RGB_10 0x0005
131#define PS3AV_CMD_VIDEO_CS_YUV444_10 0x0006
132#define PS3AV_CMD_VIDEO_CS_YUV422_10 0x0007
133#define PS3AV_CMD_VIDEO_CS_XVYCC_10 0x0008
134#define PS3AV_CMD_VIDEO_CS_RGB_12 0x0009
135#define PS3AV_CMD_VIDEO_CS_YUV444_12 0x000a
136#define PS3AV_CMD_VIDEO_CS_YUV422_12 0x000b
137#define PS3AV_CMD_VIDEO_CS_XVYCC_12 0x000c
138/* video_vid */
139#define PS3AV_CMD_VIDEO_VID_NONE 0x0000
140#define PS3AV_CMD_VIDEO_VID_480I 0x0001
141#define PS3AV_CMD_VIDEO_VID_576I 0x0003
142#define PS3AV_CMD_VIDEO_VID_480P 0x0005
143#define PS3AV_CMD_VIDEO_VID_576P 0x0006
144#define PS3AV_CMD_VIDEO_VID_1080I_60HZ 0x0007
145#define PS3AV_CMD_VIDEO_VID_1080I_50HZ 0x0008
146#define PS3AV_CMD_VIDEO_VID_720P_60HZ 0x0009
147#define PS3AV_CMD_VIDEO_VID_720P_50HZ 0x000a
148#define PS3AV_CMD_VIDEO_VID_1080P_60HZ 0x000b
149#define PS3AV_CMD_VIDEO_VID_1080P_50HZ 0x000c
150#define PS3AV_CMD_VIDEO_VID_WXGA 0x000d
151#define PS3AV_CMD_VIDEO_VID_SXGA 0x000e
152#define PS3AV_CMD_VIDEO_VID_WUXGA 0x000f
153#define PS3AV_CMD_VIDEO_VID_480I_A 0x0010
154/* video_format */
155#define PS3AV_CMD_VIDEO_FORMAT_BLACK 0x0000
156#define PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT 0x0007
157/* video_order */
158#define PS3AV_CMD_VIDEO_ORDER_RGB 0x0000
159#define PS3AV_CMD_VIDEO_ORDER_BGR 0x0001
160/* video_fmt */
161#define PS3AV_CMD_VIDEO_FMT_X8R8G8B8 0x0000
162/* video_out_format */
163#define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT 0x0000
164/* video_sync */
165#define PS3AV_CMD_VIDEO_SYNC_VSYNC 0x0001
166#define PS3AV_CMD_VIDEO_SYNC_CSYNC 0x0004
167#define PS3AV_CMD_VIDEO_SYNC_HSYNC 0x0010
168
169/* for audio module */
170/* num_of_ch */
171#define PS3AV_CMD_AUDIO_NUM_OF_CH_2 0x0000
172#define PS3AV_CMD_AUDIO_NUM_OF_CH_3 0x0001
173#define PS3AV_CMD_AUDIO_NUM_OF_CH_4 0x0002
174#define PS3AV_CMD_AUDIO_NUM_OF_CH_5 0x0003
175#define PS3AV_CMD_AUDIO_NUM_OF_CH_6 0x0004
176#define PS3AV_CMD_AUDIO_NUM_OF_CH_7 0x0005
177#define PS3AV_CMD_AUDIO_NUM_OF_CH_8 0x0006
178/* audio_fs */
179#define PS3AV_CMD_AUDIO_FS_32K 0x0001
180#define PS3AV_CMD_AUDIO_FS_44K 0x0002
181#define PS3AV_CMD_AUDIO_FS_48K 0x0003
182#define PS3AV_CMD_AUDIO_FS_88K 0x0004
183#define PS3AV_CMD_AUDIO_FS_96K 0x0005
184#define PS3AV_CMD_AUDIO_FS_176K 0x0006
185#define PS3AV_CMD_AUDIO_FS_192K 0x0007
186/* audio_word_bits */
187#define PS3AV_CMD_AUDIO_WORD_BITS_16 0x0001
188#define PS3AV_CMD_AUDIO_WORD_BITS_20 0x0002
189#define PS3AV_CMD_AUDIO_WORD_BITS_24 0x0003
190/* audio_format */
191#define PS3AV_CMD_AUDIO_FORMAT_PCM 0x0001
192#define PS3AV_CMD_AUDIO_FORMAT_BITSTREAM 0x00ff
193/* audio_source */
194#define PS3AV_CMD_AUDIO_SOURCE_SERIAL 0x0000
195#define PS3AV_CMD_AUDIO_SOURCE_SPDIF 0x0001
196/* audio_swap */
197#define PS3AV_CMD_AUDIO_SWAP_0 0x0000
198#define PS3AV_CMD_AUDIO_SWAP_1 0x0000
199/* audio_map */
200#define PS3AV_CMD_AUDIO_MAP_OUTPUT_0 0x0000
201#define PS3AV_CMD_AUDIO_MAP_OUTPUT_1 0x0001
202#define PS3AV_CMD_AUDIO_MAP_OUTPUT_2 0x0002
203#define PS3AV_CMD_AUDIO_MAP_OUTPUT_3 0x0003
204/* audio_layout */
205#define PS3AV_CMD_AUDIO_LAYOUT_2CH 0x0000
206#define PS3AV_CMD_AUDIO_LAYOUT_6CH 0x000b /* LREClr */
207#define PS3AV_CMD_AUDIO_LAYOUT_8CH 0x001f /* LREClrXY */
208/* audio_downmix */
209#define PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED 0x0000
210#define PS3AV_CMD_AUDIO_DOWNMIX_PROHIBITED 0x0001
211
212/* audio_port */
213#define PS3AV_CMD_AUDIO_PORT_HDMI_0 ( 1 << 0 )
214#define PS3AV_CMD_AUDIO_PORT_HDMI_1 ( 1 << 1 )
215#define PS3AV_CMD_AUDIO_PORT_AVMULTI_0 ( 1 << 10 )
216#define PS3AV_CMD_AUDIO_PORT_SPDIF_0 ( 1 << 20 )
217#define PS3AV_CMD_AUDIO_PORT_SPDIF_1 ( 1 << 21 )
218
219/* audio_ctrl_id */
220#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_RESET 0x0000
221#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_DE_EMPHASIS 0x0001
222#define PS3AV_CMD_AUDIO_CTRL_ID_AVCLK 0x0002
223/* audio_ctrl_data[0] reset */
224#define PS3AV_CMD_AUDIO_CTRL_RESET_NEGATE 0x0000
225#define PS3AV_CMD_AUDIO_CTRL_RESET_ASSERT 0x0001
226/* audio_ctrl_data[0] de-emphasis */
227#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_OFF 0x0000
228#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_ON 0x0001
229/* audio_ctrl_data[0] avclk */
230#define PS3AV_CMD_AUDIO_CTRL_AVCLK_22 0x0000
231#define PS3AV_CMD_AUDIO_CTRL_AVCLK_18 0x0001
232
233/* av_vid */
234/* do not use these params directly, use vid_video2av */
235#define PS3AV_CMD_AV_VID_480I 0x0000
236#define PS3AV_CMD_AV_VID_480P 0x0001
237#define PS3AV_CMD_AV_VID_720P_60HZ 0x0002
238#define PS3AV_CMD_AV_VID_1080I_60HZ 0x0003
239#define PS3AV_CMD_AV_VID_1080P_60HZ 0x0004
240#define PS3AV_CMD_AV_VID_576I 0x0005
241#define PS3AV_CMD_AV_VID_576P 0x0006
242#define PS3AV_CMD_AV_VID_720P_50HZ 0x0007
243#define PS3AV_CMD_AV_VID_1080I_50HZ 0x0008
244#define PS3AV_CMD_AV_VID_1080P_50HZ 0x0009
245#define PS3AV_CMD_AV_VID_WXGA 0x000a
246#define PS3AV_CMD_AV_VID_SXGA 0x000b
247#define PS3AV_CMD_AV_VID_WUXGA 0x000c
248/* av_cs_out av_cs_in */
249/* use cs_video2av() */
250#define PS3AV_CMD_AV_CS_RGB_8 0x0000
251#define PS3AV_CMD_AV_CS_YUV444_8 0x0001
252#define PS3AV_CMD_AV_CS_YUV422_8 0x0002
253#define PS3AV_CMD_AV_CS_XVYCC_8 0x0003
254#define PS3AV_CMD_AV_CS_RGB_10 0x0004
255#define PS3AV_CMD_AV_CS_YUV444_10 0x0005
256#define PS3AV_CMD_AV_CS_YUV422_10 0x0006
257#define PS3AV_CMD_AV_CS_XVYCC_10 0x0007
258#define PS3AV_CMD_AV_CS_RGB_12 0x0008
259#define PS3AV_CMD_AV_CS_YUV444_12 0x0009
260#define PS3AV_CMD_AV_CS_YUV422_12 0x000a
261#define PS3AV_CMD_AV_CS_XVYCC_12 0x000b
262#define PS3AV_CMD_AV_CS_8 0x0000
263#define PS3AV_CMD_AV_CS_10 0x0001
264#define PS3AV_CMD_AV_CS_12 0x0002
265/* dither */
266#define PS3AV_CMD_AV_DITHER_OFF 0x0000
267#define PS3AV_CMD_AV_DITHER_ON 0x0001
268#define PS3AV_CMD_AV_DITHER_8BIT 0x0000
269#define PS3AV_CMD_AV_DITHER_10BIT 0x0002
270#define PS3AV_CMD_AV_DITHER_12BIT 0x0004
271/* super_white */
272#define PS3AV_CMD_AV_SUPER_WHITE_OFF 0x0000
273#define PS3AV_CMD_AV_SUPER_WHITE_ON 0x0001
274/* aspect */
275#define PS3AV_CMD_AV_ASPECT_16_9 0x0000
276#define PS3AV_CMD_AV_ASPECT_4_3 0x0001
277/* video_cs_cnv() */
278#define PS3AV_CMD_VIDEO_CS_RGB 0x0001
279#define PS3AV_CMD_VIDEO_CS_YUV422 0x0002
280#define PS3AV_CMD_VIDEO_CS_YUV444 0x0003
281
282/* for automode */
283#define PS3AV_RESBIT_720x480P 0x0003 /* 0x0001 | 0x0002 */
284#define PS3AV_RESBIT_720x576P 0x0003 /* 0x0001 | 0x0002 */
285#define PS3AV_RESBIT_1280x720P 0x0004
286#define PS3AV_RESBIT_1920x1080I 0x0008
287#define PS3AV_RESBIT_1920x1080P 0x4000
288#define PS3AV_RES_MASK_60 (PS3AV_RESBIT_720x480P \
289 | PS3AV_RESBIT_1280x720P \
290 | PS3AV_RESBIT_1920x1080I \
291 | PS3AV_RESBIT_1920x1080P)
292#define PS3AV_RES_MASK_50 (PS3AV_RESBIT_720x576P \
293 | PS3AV_RESBIT_1280x720P \
294 | PS3AV_RESBIT_1920x1080I \
295 | PS3AV_RESBIT_1920x1080P)
296
297#define PS3AV_MONITOR_TYPE_HDMI 1 /* HDMI */
298#define PS3AV_MONITOR_TYPE_DVI 2 /* DVI */
299#define PS3AV_DEFAULT_HDMI_VID_REG_60 PS3AV_CMD_VIDEO_VID_480P
300#define PS3AV_DEFAULT_AVMULTI_VID_REG_60 PS3AV_CMD_VIDEO_VID_480I
301#define PS3AV_DEFAULT_HDMI_VID_REG_50 PS3AV_CMD_VIDEO_VID_576P
302#define PS3AV_DEFAULT_AVMULTI_VID_REG_50 PS3AV_CMD_VIDEO_VID_576I
303#define PS3AV_DEFAULT_DVI_VID PS3AV_CMD_VIDEO_VID_480P
304
305#define PS3AV_REGION_60 0x01
306#define PS3AV_REGION_50 0x02
307#define PS3AV_REGION_RGB 0x10
308
309#define get_status(buf) (((__u32 *)buf)[2])
310#define PS3AV_HDR_SIZE 4 /* version + size */
311
312/* for video mode */
313#define PS3AV_MODE_MASK 0x000F
314#define PS3AV_MODE_HDCP_OFF 0x1000 /* Retail PS3 product doesn't support this */
315#define PS3AV_MODE_DITHER 0x0800
316#define PS3AV_MODE_FULL 0x0080
317#define PS3AV_MODE_DVI 0x0040
318#define PS3AV_MODE_RGB 0x0020
319
320
321/** command packet structure **/
322struct ps3av_send_hdr {
323 u16 version;
324 u16 size; /* size of command packet */
325 u32 cid; /* command id */
326};
327
328struct ps3av_reply_hdr {
329 u16 version;
330 u16 size;
331 u32 cid;
332 u32 status;
333};
334
335/* backend: initialization */
336struct ps3av_pkt_av_init {
337 struct ps3av_send_hdr send_hdr;
338 u32 event_bit;
339};
340
341/* backend: finalize */
342struct ps3av_pkt_av_fin {
343 struct ps3av_send_hdr send_hdr;
344 /* recv */
345 u32 reserved;
346};
347
348/* backend: get port */
349struct ps3av_pkt_av_get_hw_conf {
350 struct ps3av_send_hdr send_hdr;
351 /* recv */
352 u32 status;
353 u16 num_of_hdmi; /* out: number of hdmi */
354 u16 num_of_avmulti; /* out: number of avmulti */
355 u16 num_of_spdif; /* out: number of hdmi */
356 u16 reserved;
357};
358
359/* backend: get monitor info */
360struct ps3av_info_resolution {
361 u32 res_bits;
362 u32 native;
363};
364
365struct ps3av_info_cs {
366 u8 rgb;
367 u8 yuv444;
368 u8 yuv422;
369 u8 reserved;
370};
371
372struct ps3av_info_color {
373 u16 red_x;
374 u16 red_y;
375 u16 green_x;
376 u16 green_y;
377 u16 blue_x;
378 u16 blue_y;
379 u16 white_x;
380 u16 white_y;
381 u32 gamma;
382};
383
384struct ps3av_info_audio {
385 u8 type;
386 u8 max_num_of_ch;
387 u8 fs;
388 u8 sbit;
389};
390
391struct ps3av_info_monitor {
392 u8 avport;
393 u8 monitor_id[10];
394 u8 monitor_type;
395 u8 monitor_name[16];
396 struct ps3av_info_resolution res_60;
397 struct ps3av_info_resolution res_50;
398 struct ps3av_info_resolution res_other;
399 struct ps3av_info_resolution res_vesa;
400 struct ps3av_info_cs cs;
401 struct ps3av_info_color color;
402 u8 supported_ai;
403 u8 speaker_info;
404 u8 num_of_audio_block;
405 struct ps3av_info_audio audio[0]; /* 0 or more audio blocks */
406 u8 reserved[169];
407} __attribute__ ((packed));
408
409struct ps3av_pkt_av_get_monitor_info {
410 struct ps3av_send_hdr send_hdr;
411 u16 avport; /* in: avport */
412 u16 reserved;
413 /* recv */
414 struct ps3av_info_monitor info; /* out: monitor info */
415};
416
417/* backend: enable/disable event */
418struct ps3av_pkt_av_event {
419 struct ps3av_send_hdr send_hdr;
420 u32 event_bit; /* in */
421};
422
423/* backend: video cs param */
424struct ps3av_pkt_av_video_cs {
425 struct ps3av_send_hdr send_hdr;
426 u16 avport; /* in: avport */
427 u16 av_vid; /* in: video resolution */
428 u16 av_cs_out; /* in: output color space */
429 u16 av_cs_in; /* in: input color space */
430 u8 dither; /* in: dither bit length */
431 u8 bitlen_out; /* in: bit length */
432 u8 super_white; /* in: super white */
433 u8 aspect; /* in: aspect ratio */
434};
435
436/* backend: video mute */
437struct ps3av_av_mute {
438 u16 avport; /* in: avport */
439 u16 mute; /* in: mute on/off */
440};
441
442struct ps3av_pkt_av_video_mute {
443 struct ps3av_send_hdr send_hdr;
444 struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
445};
446
447/* backend: video disable signal */
448struct ps3av_pkt_av_video_disable_sig {
449 struct ps3av_send_hdr send_hdr;
450 u16 avport; /* in: avport */
451 u16 reserved;
452};
453
454/* backend: audio param */
455struct ps3av_audio_info_frame {
456 struct pb1_bit {
457 u8 ct:4;
458 u8 rsv:1;
459 u8 cc:3;
460 } pb1;
461 struct pb2_bit {
462 u8 rsv:3;
463 u8 sf:3;
464 u8 ss:2;
465 } pb2;
466 u8 pb3;
467 u8 pb4;
468 struct pb5_bit {
469 u8 dm:1;
470 u8 lsv:4;
471 u8 rsv:3;
472 } pb5;
473};
474
475struct ps3av_pkt_av_audio_param {
476 struct ps3av_send_hdr send_hdr;
477 u16 avport; /* in: avport */
478 u16 reserved;
479 u8 mclk; /* in: audio mclk */
480 u8 ns[3]; /* in: audio ns val */
481 u8 enable; /* in: audio enable */
482 u8 swaplr; /* in: audio swap */
483 u8 fifomap; /* in: audio fifomap */
484 u8 inputctrl; /* in: audio input ctrl */
485 u8 inputlen; /* in: sample bit size */
486 u8 layout; /* in: speaker layout param */
487 struct ps3av_audio_info_frame info; /* in: info */
488 u8 chstat[5]; /* in: ch stat */
489};
490
491/* backend: audio_mute */
492struct ps3av_pkt_av_audio_mute {
493 struct ps3av_send_hdr send_hdr;
494 struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
495};
496
497/* backend: hdmi_mode */
498struct ps3av_pkt_av_hdmi_mode {
499 struct ps3av_send_hdr send_hdr;
500 u8 mode; /* in: hdmi_mode */
501 u8 reserved0;
502 u8 reserved1;
503 u8 reserved2;
504};
505
506/* backend: tv_mute */
507struct ps3av_pkt_av_tv_mute {
508 struct ps3av_send_hdr send_hdr;
509 u16 avport; /* in: avport HDMI only */
510 u16 mute; /* in: mute */
511};
512
513/* video: initialize */
514struct ps3av_pkt_video_init {
515 struct ps3av_send_hdr send_hdr;
516 /* recv */
517 u32 reserved;
518};
519
520/* video: mode setting */
521struct ps3av_pkt_video_mode {
522 struct ps3av_send_hdr send_hdr;
523 u32 video_head; /* in: head */
524 u32 reserved;
525 u32 video_vid; /* in: video resolution */
526 u16 reserved1;
527 u16 width; /* in: width in pixel */
528 u16 reserved2;
529 u16 height; /* in: height in pixel */
530 u32 pitch; /* in: line size in byte */
531 u32 video_out_format; /* in: out format */
532 u32 video_format; /* in: input frame buffer format */
533 u8 reserved3;
534 u8 reserved4;
535 u16 video_order; /* in: input RGB order */
536 u32 reserved5;
537};
538
539/* video: format */
540struct ps3av_pkt_video_format {
541 struct ps3av_send_hdr send_hdr;
542 u32 video_head; /* in: head */
543 u32 video_format; /* in: frame buffer format */
544 u16 reserved;
545 u16 video_order; /* in: input RGB order */
546};
547
548/* video: pitch */
549struct ps3av_pkt_video_pitch {
550 u16 version;
551 u16 size; /* size of command packet */
552 u32 cid; /* command id */
553 u32 video_head; /* in: head */
554 u32 pitch; /* in: line size in byte */
555};
556
557/* audio: initialize */
558struct ps3av_pkt_audio_init {
559 struct ps3av_send_hdr send_hdr;
560 /* recv */
561 u32 reserved;
562};
563
564/* audio: mode setting */
565struct ps3av_pkt_audio_mode {
566 struct ps3av_send_hdr send_hdr;
567 u8 avport; /* in: avport */
568 u8 reserved0[3];
569 u32 mask; /* in: mask */
570 u32 audio_num_of_ch; /* in: number of ch */
571 u32 audio_fs; /* in: sampling freq */
572 u32 audio_word_bits; /* in: sample bit size */
573 u32 audio_format; /* in: audio output format */
574 u32 audio_source; /* in: audio source */
575 u8 audio_enable[4]; /* in: audio enable */
576 u8 audio_swap[4]; /* in: audio swap */
577 u8 audio_map[4]; /* in: audio map */
578 u32 audio_layout; /* in: speaker layout */
579 u32 audio_downmix; /* in: audio downmix permission */
580 u32 audio_downmix_level;
581 u8 audio_cs_info[8]; /* in: IEC channel status */
582};
583
584/* audio: mute */
585struct ps3av_audio_mute {
586 u8 avport; /* in: opt_port optical */
587 u8 reserved[3];
588 u32 mute; /* in: mute */
589};
590
591struct ps3av_pkt_audio_mute {
592 struct ps3av_send_hdr send_hdr;
593 struct ps3av_audio_mute mute[PS3AV_OPT_PORT_MAX];
594};
595
596/* audio: active/inactive */
597struct ps3av_pkt_audio_active {
598 struct ps3av_send_hdr send_hdr;
599 u32 audio_port; /* in: audio active/inactive port */
600};
601
602/* audio: SPDIF user bit */
603struct ps3av_pkt_audio_spdif_bit {
604 u16 version;
605 u16 size; /* size of command packet */
606 u32 cid; /* command id */
607 u8 avport; /* in: avport SPDIF only */
608 u8 reserved[3];
609 u32 audio_port; /* in: SPDIF only */
610 u32 spdif_bit_data[12]; /* in: user bit data */
611};
612
613/* audio: audio control */
614struct ps3av_pkt_audio_ctrl {
615 u16 version;
616 u16 size; /* size of command packet */
617 u32 cid; /* command id */
618 u32 audio_ctrl_id; /* in: control id */
619 u32 audio_ctrl_data[4]; /* in: control data */
620};
621
622/* avb:param */
623#define PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE \
624 (PS3AV_AVB_NUM_VIDEO*sizeof(struct ps3av_pkt_video_mode) + \
625 PS3AV_AVB_NUM_AUDIO*sizeof(struct ps3av_pkt_audio_mode) + \
626 PS3AV_AVB_NUM_AV_VIDEO*sizeof(struct ps3av_pkt_av_video_cs) + \
627 PS3AV_AVB_NUM_AV_AUDIO*sizeof(struct ps3av_pkt_av_audio_param))
628
629struct ps3av_pkt_avb_param {
630 struct ps3av_send_hdr send_hdr;
631 u16 num_of_video_pkt;
632 u16 num_of_audio_pkt;
633 u16 num_of_av_video_pkt;
634 u16 num_of_av_audio_pkt;
635 /*
636 * The actual buffer layout depends on the fields above:
637 *
638 * struct ps3av_pkt_video_mode video[num_of_video_pkt];
639 * struct ps3av_pkt_audio_mode audio[num_of_audio_pkt];
640 * struct ps3av_pkt_av_video_cs av_video[num_of_av_video_pkt];
641 * struct ps3av_pkt_av_audio_param av_audio[num_of_av_audio_pkt];
642 */
643 u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE];
644};
645
646struct ps3av {
647 int available;
648 struct semaphore sem;
649 struct semaphore ping;
650 struct semaphore pong;
651 struct mutex mutex;
652 int open_count;
653 struct ps3_vuart_port_device *dev;
654
655 int region;
656 struct ps3av_pkt_av_get_hw_conf av_hw_conf;
657 u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
658 u32 opt_port[PS3AV_OPT_PORT_MAX];
659 u32 head[PS3AV_HEAD_MAX];
660 u32 audio_port;
661 int ps3av_mode;
662 int ps3av_mode_old;
663};
664
665/** command status **/
666#define PS3AV_STATUS_SUCCESS 0x0000 /* success */
667#define PS3AV_STATUS_RECEIVE_VUART_ERROR 0x0001 /* receive vuart error */
668#define PS3AV_STATUS_SYSCON_COMMUNICATE_FAIL 0x0002 /* syscon communication error */
669#define PS3AV_STATUS_INVALID_COMMAND 0x0003 /* obsolete invalid CID */
670#define PS3AV_STATUS_INVALID_PORT 0x0004 /* invalid port number */
671#define PS3AV_STATUS_INVALID_VID 0x0005 /* invalid video format */
672#define PS3AV_STATUS_INVALID_COLOR_SPACE 0x0006 /* invalid video colose space */
673#define PS3AV_STATUS_INVALID_FS 0x0007 /* invalid audio sampling freq */
674#define PS3AV_STATUS_INVALID_AUDIO_CH 0x0008 /* invalid audio channel number */
675#define PS3AV_STATUS_UNSUPPORTED_VERSION 0x0009 /* version mismatch */
676#define PS3AV_STATUS_INVALID_SAMPLE_SIZE 0x000a /* invalid audio sample bit size */
677#define PS3AV_STATUS_FAILURE 0x000b /* other failures */
678#define PS3AV_STATUS_UNSUPPORTED_COMMAND 0x000c /* unsupported cid */
679#define PS3AV_STATUS_BUFFER_OVERFLOW 0x000d /* write buffer overflow */
680#define PS3AV_STATUS_INVALID_VIDEO_PARAM 0x000e /* invalid video param */
681#define PS3AV_STATUS_NO_SEL 0x000f /* not exist selector */
682#define PS3AV_STATUS_INVALID_AV_PARAM 0x0010 /* invalid backend param */
683#define PS3AV_STATUS_INVALID_AUDIO_PARAM 0x0011 /* invalid audio param */
684#define PS3AV_STATUS_UNSUPPORTED_HDMI_MODE 0x0012 /* unsupported hdmi mode */
685#define PS3AV_STATUS_NO_SYNC_HEAD 0x0013 /* sync head failed */
686
687extern void ps3av_set_hdr(u32, u16, struct ps3av_send_hdr *);
688extern int ps3av_do_pkt(u32, u16, size_t, struct ps3av_send_hdr *);
689
690extern int ps3av_cmd_init(void);
691extern int ps3av_cmd_fin(void);
692extern int ps3av_cmd_av_video_mute(int, u32 *, u32);
693extern int ps3av_cmd_av_video_disable_sig(u32);
694extern int ps3av_cmd_av_tv_mute(u32, u32);
695extern int ps3av_cmd_enable_event(void);
696extern int ps3av_cmd_av_hdmi_mode(u8);
697extern u32 ps3av_cmd_set_av_video_cs(void *, u32, int, int, int, u32);
698extern u32 ps3av_cmd_set_video_mode(void *, u32, int, int, u32);
699extern int ps3av_cmd_video_format_black(u32, u32, u32);
700extern int ps3av_cmd_av_audio_mute(int, u32 *, u32);
701extern u32 ps3av_cmd_set_av_audio_param(void *, u32,
702 const struct ps3av_pkt_audio_mode *,
703 u32);
704extern void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *, u32, u32,
705 u32, u32, u32, u32);
706extern int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *);
707extern int ps3av_cmd_audio_mute(int, u32 *, u32);
708extern int ps3av_cmd_audio_active(int, u32);
709extern int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *, u32);
710extern int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *);
711#ifdef PS3AV_DEBUG
712extern void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *);
713extern void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *);
714#else
715static inline void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf) {}
716static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) {}
717#endif
718extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
719 u32);
720
721extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
722 const void *buf, unsigned long size);
723extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
724 unsigned long size, int timeout);
725
726extern int ps3av_set_video_mode(u32, int);
727extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
728extern int ps3av_set_mode(u32, int);
729extern int ps3av_get_mode(void);
730extern int ps3av_get_scanmode(int);
731extern int ps3av_get_refresh_rate(int);
732extern int ps3av_video_mode2res(u32, u32 *, u32 *);
733extern int ps3av_video_mute(int);
734extern int ps3av_audio_mute(int);
735extern int ps3av_dev_open(void);
736extern int ps3av_dev_close(void);
737
738#endif /* _ASM_POWERPC_PS3AV_H_ */