1 /* 2 * PS3 AV backend support. 3 * 4 * Copyright (C) 2007 Sony Computer Entertainment Inc. 5 * Copyright 2007 Sony Corp. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/delay.h> 24 #include <linux/notifier.h> 25 #include <linux/ioctl.h> 26 #include <linux/fb.h> 27 28 #include <asm/firmware.h> 29 #include <asm/ps3av.h> 30 #include <asm/ps3.h> 31 32 #include "vuart.h" 33 34 #define BUFSIZE 4096 /* vuart buf size */ 35 #define PS3AV_BUF_SIZE 512 /* max packet size */ 36 37 static int safe_mode; 38 39 static int timeout = 5000; /* in msec ( 5 sec ) */ 40 module_param(timeout, int, 0644); 41 42 static struct ps3av { 43 struct mutex mutex; 44 struct work_struct work; 45 struct completion done; 46 struct workqueue_struct *wq; 47 int open_count; 48 struct ps3_system_bus_device *dev; 49 50 int region; 51 struct ps3av_pkt_av_get_hw_conf av_hw_conf; 52 u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX]; 53 u32 opt_port[PS3AV_OPT_PORT_MAX]; 54 u32 head[PS3AV_HEAD_MAX]; 55 u32 audio_port; 56 int ps3av_mode; 57 int ps3av_mode_old; 58 union { 59 struct ps3av_reply_hdr reply_hdr; 60 u8 raw[PS3AV_BUF_SIZE]; 61 } recv_buf; 62 void (*flip_ctl)(int on, void *data); 63 void *flip_data; 64 } *ps3av; 65 66 /* color space */ 67 #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8 68 #define RGB8 PS3AV_CMD_VIDEO_CS_RGB_8 69 /* format */ 70 #define XRGB PS3AV_CMD_VIDEO_FMT_X8R8G8B8 71 /* aspect */ 72 #define A_N PS3AV_CMD_AV_ASPECT_4_3 73 #define A_W PS3AV_CMD_AV_ASPECT_16_9 74 static const struct avset_video_mode { 75 u32 cs; 76 u32 fmt; 77 u32 vid; 78 u32 aspect; 79 u32 x; 80 u32 y; 81 } video_mode_table[] = { 82 { 0, }, /* auto */ 83 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480}, 84 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480}, 85 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720}, 86 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080}, 87 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080}, 88 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576}, 89 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576}, 90 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720}, 91 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080}, 92 {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080}, 93 { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768}, 94 { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024}, 95 { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200}, 96 }; 97 98 /* supported CIDs */ 99 static u32 cmd_table[] = { 100 /* init */ 101 PS3AV_CID_AV_INIT, 102 PS3AV_CID_AV_FIN, 103 PS3AV_CID_VIDEO_INIT, 104 PS3AV_CID_AUDIO_INIT, 105 106 /* set */ 107 PS3AV_CID_AV_ENABLE_EVENT, 108 PS3AV_CID_AV_DISABLE_EVENT, 109 110 PS3AV_CID_AV_VIDEO_CS, 111 PS3AV_CID_AV_VIDEO_MUTE, 112 PS3AV_CID_AV_VIDEO_DISABLE_SIG, 113 PS3AV_CID_AV_AUDIO_PARAM, 114 PS3AV_CID_AV_AUDIO_MUTE, 115 PS3AV_CID_AV_HDMI_MODE, 116 PS3AV_CID_AV_TV_MUTE, 117 118 PS3AV_CID_VIDEO_MODE, 119 PS3AV_CID_VIDEO_FORMAT, 120 PS3AV_CID_VIDEO_PITCH, 121 122 PS3AV_CID_AUDIO_MODE, 123 PS3AV_CID_AUDIO_MUTE, 124 PS3AV_CID_AUDIO_ACTIVE, 125 PS3AV_CID_AUDIO_INACTIVE, 126 PS3AV_CID_AVB_PARAM, 127 128 /* get */ 129 PS3AV_CID_AV_GET_HW_CONF, 130 PS3AV_CID_AV_GET_MONITOR_INFO, 131 132 /* event */ 133 PS3AV_CID_EVENT_UNPLUGGED, 134 PS3AV_CID_EVENT_PLUGGED, 135 PS3AV_CID_EVENT_HDCP_DONE, 136 PS3AV_CID_EVENT_HDCP_FAIL, 137 PS3AV_CID_EVENT_HDCP_AUTH, 138 PS3AV_CID_EVENT_HDCP_ERROR, 139 140 0 141 }; 142 143 #define PS3AV_EVENT_CMD_MASK 0x10000000 144 #define PS3AV_EVENT_ID_MASK 0x0000ffff 145 #define PS3AV_CID_MASK 0xffffffff 146 #define PS3AV_REPLY_BIT 0x80000000 147 148 #define ps3av_event_get_port_id(cid) ((cid >> 16) & 0xff) 149 150 static u32 *ps3av_search_cmd_table(u32 cid, u32 mask) 151 { 152 u32 *table; 153 int i; 154 155 table = cmd_table; 156 for (i = 0;; table++, i++) { 157 if ((*table & mask) == (cid & mask)) 158 break; 159 if (*table == 0) 160 return NULL; 161 } 162 return table; 163 } 164 165 static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) 166 { 167 u32 *table; 168 169 if (hdr->cid & PS3AV_EVENT_CMD_MASK) { 170 table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK); 171 if (table) 172 dev_dbg(&ps3av->dev->core, 173 "recv event packet cid:%08x port:0x%x size:%d\n", 174 hdr->cid, ps3av_event_get_port_id(hdr->cid), 175 hdr->size); 176 else 177 printk(KERN_ERR 178 "%s: failed event packet, cid:%08x size:%d\n", 179 __func__, hdr->cid, hdr->size); 180 return 1; /* receive event packet */ 181 } 182 return 0; 183 } 184 185 186 #define POLLING_INTERVAL 25 /* in msec */ 187 188 static int ps3av_vuart_write(struct ps3_system_bus_device *dev, 189 const void *buf, unsigned long size) 190 { 191 int error; 192 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); 193 error = ps3_vuart_write(dev, buf, size); 194 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); 195 return error ? error : size; 196 } 197 198 static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf, 199 unsigned long size, int timeout) 200 { 201 int error; 202 int loopcnt = 0; 203 204 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); 205 timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL; 206 while (loopcnt++ <= timeout) { 207 error = ps3_vuart_read(dev, buf, size); 208 if (!error) 209 return size; 210 if (error != -EAGAIN) { 211 printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", 212 __func__, error); 213 return error; 214 } 215 msleep(POLLING_INTERVAL); 216 } 217 return -EWOULDBLOCK; 218 } 219 220 static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, 221 struct ps3av_reply_hdr *recv_buf, int write_len, 222 int read_len) 223 { 224 int res; 225 u32 cmd; 226 int event; 227 228 if (!ps3av) 229 return -ENODEV; 230 231 /* send pkt */ 232 res = ps3av_vuart_write(ps3av->dev, send_buf, write_len); 233 if (res < 0) { 234 dev_dbg(&ps3av->dev->core, 235 "%s: ps3av_vuart_write() failed (result=%d)\n", 236 __func__, res); 237 return res; 238 } 239 240 /* recv pkt */ 241 cmd = send_buf->cid; 242 do { 243 /* read header */ 244 res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE, 245 timeout); 246 if (res != PS3AV_HDR_SIZE) { 247 dev_dbg(&ps3av->dev->core, 248 "%s: ps3av_vuart_read() failed (result=%d)\n", 249 __func__, res); 250 return res; 251 } 252 253 /* read body */ 254 res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid, 255 recv_buf->size, timeout); 256 if (res < 0) { 257 dev_dbg(&ps3av->dev->core, 258 "%s: ps3av_vuart_read() failed (result=%d)\n", 259 __func__, res); 260 return res; 261 } 262 res += PS3AV_HDR_SIZE; /* total len */ 263 event = ps3av_parse_event_packet(recv_buf); 264 /* ret > 0 event packet */ 265 } while (event); 266 267 if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { 268 dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n", 269 __func__, recv_buf->cid); 270 return -EINVAL; 271 } 272 273 return 0; 274 } 275 276 static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf, 277 const struct ps3av_reply_hdr *recv_buf, 278 int user_buf_size) 279 { 280 int return_len; 281 282 if (recv_buf->version != PS3AV_VERSION) { 283 dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n", 284 recv_buf->version); 285 return -EFAULT; 286 } 287 return_len = recv_buf->size + PS3AV_HDR_SIZE; 288 if (return_len > user_buf_size) 289 return_len = user_buf_size; 290 memcpy(cmd_buf, recv_buf, return_len); 291 return 0; /* success */ 292 } 293 294 void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr) 295 { 296 hdr->version = PS3AV_VERSION; 297 hdr->size = size - PS3AV_HDR_SIZE; 298 hdr->cid = cid; 299 } 300 301 int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, 302 struct ps3av_send_hdr *buf) 303 { 304 int res = 0; 305 u32 *table; 306 307 BUG_ON(!ps3av); 308 309 mutex_lock(&ps3av->mutex); 310 311 table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); 312 BUG_ON(!table); 313 BUG_ON(send_len < PS3AV_HDR_SIZE); 314 BUG_ON(usr_buf_size < send_len); 315 BUG_ON(usr_buf_size > PS3AV_BUF_SIZE); 316 317 /* create header */ 318 ps3av_set_hdr(cid, send_len, buf); 319 320 /* send packet via vuart */ 321 res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len, 322 usr_buf_size); 323 if (res < 0) { 324 printk(KERN_ERR 325 "%s: ps3av_send_cmd_pkt() failed (result=%d)\n", 326 __func__, res); 327 goto err; 328 } 329 330 /* process reply packet */ 331 res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr, 332 usr_buf_size); 333 if (res < 0) { 334 printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", 335 __func__, res); 336 goto err; 337 } 338 339 mutex_unlock(&ps3av->mutex); 340 return 0; 341 342 err: 343 mutex_unlock(&ps3av->mutex); 344 printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); 345 return res; 346 } 347 348 static int ps3av_set_av_video_mute(u32 mute) 349 { 350 int i, num_of_av_port, res; 351 352 num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + 353 ps3av->av_hw_conf.num_of_avmulti; 354 /* video mute on */ 355 for (i = 0; i < num_of_av_port; i++) { 356 res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute); 357 if (res < 0) 358 return -1; 359 } 360 361 return 0; 362 } 363 364 static int ps3av_set_video_disable_sig(void) 365 { 366 int i, num_of_hdmi_port, num_of_av_port, res; 367 368 num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi; 369 num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + 370 ps3av->av_hw_conf.num_of_avmulti; 371 372 /* tv mute */ 373 for (i = 0; i < num_of_hdmi_port; i++) { 374 res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], 375 PS3AV_CMD_MUTE_ON); 376 if (res < 0) 377 return -1; 378 } 379 msleep(100); 380 381 /* video mute on */ 382 for (i = 0; i < num_of_av_port; i++) { 383 res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]); 384 if (res < 0) 385 return -1; 386 if (i < num_of_hdmi_port) { 387 res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], 388 PS3AV_CMD_MUTE_OFF); 389 if (res < 0) 390 return -1; 391 } 392 } 393 msleep(300); 394 395 return 0; 396 } 397 398 static int ps3av_set_audio_mute(u32 mute) 399 { 400 int i, num_of_av_port, num_of_opt_port, res; 401 402 num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + 403 ps3av->av_hw_conf.num_of_avmulti; 404 num_of_opt_port = ps3av->av_hw_conf.num_of_spdif; 405 406 for (i = 0; i < num_of_av_port; i++) { 407 res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute); 408 if (res < 0) 409 return -1; 410 } 411 for (i = 0; i < num_of_opt_port; i++) { 412 res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute); 413 if (res < 0) 414 return -1; 415 } 416 417 return 0; 418 } 419 420 int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) 421 { 422 struct ps3av_pkt_avb_param avb_param; 423 int i, num_of_audio, vid, res; 424 struct ps3av_pkt_audio_mode audio_mode; 425 u32 len = 0; 426 427 num_of_audio = ps3av->av_hw_conf.num_of_hdmi + 428 ps3av->av_hw_conf.num_of_avmulti + 429 ps3av->av_hw_conf.num_of_spdif; 430 431 avb_param.num_of_video_pkt = 0; 432 avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */ 433 avb_param.num_of_av_video_pkt = 0; 434 avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi; 435 436 vid = video_mode_table[ps3av->ps3av_mode].vid; 437 438 /* audio mute */ 439 ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON); 440 441 /* audio inactive */ 442 res = ps3av_cmd_audio_active(0, ps3av->audio_port); 443 if (res < 0) 444 dev_dbg(&ps3av->dev->core, 445 "ps3av_cmd_audio_active OFF failed\n"); 446 447 /* audio_pkt */ 448 for (i = 0; i < num_of_audio; i++) { 449 ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch, 450 fs, word_bits, format, source); 451 if (i < ps3av->av_hw_conf.num_of_hdmi) { 452 /* hdmi only */ 453 len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len], 454 ps3av->av_port[i], 455 &audio_mode, vid); 456 } 457 /* audio_mode pkt should be sent separately */ 458 res = ps3av_cmd_audio_mode(&audio_mode); 459 if (res < 0) 460 dev_dbg(&ps3av->dev->core, 461 "ps3av_cmd_audio_mode failed, port:%x\n", i); 462 } 463 464 /* send command using avb pkt */ 465 len += offsetof(struct ps3av_pkt_avb_param, buf); 466 res = ps3av_cmd_avb_param(&avb_param, len); 467 if (res < 0) 468 dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); 469 470 /* audio mute */ 471 ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF); 472 473 /* audio active */ 474 res = ps3av_cmd_audio_active(1, ps3av->audio_port); 475 if (res < 0) 476 dev_dbg(&ps3av->dev->core, 477 "ps3av_cmd_audio_active ON failed\n"); 478 479 return 0; 480 } 481 482 EXPORT_SYMBOL_GPL(ps3av_set_audio_mode); 483 484 static int ps3av_set_videomode(void) 485 { 486 /* av video mute */ 487 ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); 488 489 /* wake up ps3avd to do the actual video mode setting */ 490 queue_work(ps3av->wq, &ps3av->work); 491 492 return 0; 493 } 494 495 static void ps3av_set_videomode_packet(u32 id) 496 { 497 struct ps3av_pkt_avb_param avb_param; 498 unsigned int i; 499 u32 len = 0, av_video_cs; 500 const struct avset_video_mode *video_mode; 501 int res; 502 503 video_mode = &video_mode_table[id & PS3AV_MODE_MASK]; 504 505 avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ 506 avb_param.num_of_audio_pkt = 0; 507 avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi + 508 ps3av->av_hw_conf.num_of_avmulti; 509 avb_param.num_of_av_audio_pkt = 0; 510 511 /* video_pkt */ 512 for (i = 0; i < avb_param.num_of_video_pkt; i++) 513 len += ps3av_cmd_set_video_mode(&avb_param.buf[len], 514 ps3av->head[i], video_mode->vid, 515 video_mode->fmt, id); 516 /* av_video_pkt */ 517 for (i = 0; i < avb_param.num_of_av_video_pkt; i++) { 518 if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB) 519 av_video_cs = RGB8; 520 else 521 av_video_cs = video_mode->cs; 522 #ifndef PS3AV_HDMI_YUV 523 if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || 524 ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) 525 av_video_cs = RGB8; /* use RGB for HDMI */ 526 #endif 527 len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], 528 ps3av->av_port[i], 529 video_mode->vid, av_video_cs, 530 video_mode->aspect, id); 531 } 532 /* send command using avb pkt */ 533 len += offsetof(struct ps3av_pkt_avb_param, buf); 534 res = ps3av_cmd_avb_param(&avb_param, len); 535 if (res == PS3AV_STATUS_NO_SYNC_HEAD) 536 printk(KERN_WARNING 537 "%s: Command failed. Please try your request again. \n", 538 __func__); 539 else if (res) 540 dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); 541 } 542 543 static void ps3av_set_videomode_cont(u32 id, u32 old_id) 544 { 545 static int vesa; 546 int res; 547 548 /* video signal off */ 549 ps3av_set_video_disable_sig(); 550 551 /* 552 * AV backend needs non-VESA mode setting at least one time 553 * when VESA mode is used. 554 */ 555 if (vesa == 0 && (id & PS3AV_MODE_MASK) >= PS3AV_MODE_WXGA) { 556 /* vesa mode */ 557 ps3av_set_videomode_packet(PS3AV_MODE_480P); 558 } 559 vesa = 1; 560 561 /* Retail PS3 product doesn't support this */ 562 if (id & PS3AV_MODE_HDCP_OFF) { 563 res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); 564 if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) 565 dev_dbg(&ps3av->dev->core, "Not supported\n"); 566 else if (res) 567 dev_dbg(&ps3av->dev->core, 568 "ps3av_cmd_av_hdmi_mode failed\n"); 569 } else if (old_id & PS3AV_MODE_HDCP_OFF) { 570 res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); 571 if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) 572 dev_dbg(&ps3av->dev->core, 573 "ps3av_cmd_av_hdmi_mode failed\n"); 574 } 575 576 ps3av_set_videomode_packet(id); 577 578 msleep(1500); 579 /* av video mute */ 580 ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF); 581 } 582 583 static void ps3avd(struct work_struct *work) 584 { 585 ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old); 586 complete(&ps3av->done); 587 } 588 589 #define SHIFT_50 0 590 #define SHIFT_60 4 591 #define SHIFT_VESA 8 592 593 static const struct { 594 unsigned mask : 19; 595 unsigned id : 4; 596 } ps3av_preferred_modes[] = { 597 { PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA }, 598 { PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 }, 599 { PS3AV_RESBIT_1920x1080P << SHIFT_50, PS3AV_MODE_1080P50 }, 600 { PS3AV_RESBIT_1920x1080I << SHIFT_60, PS3AV_MODE_1080I60 }, 601 { PS3AV_RESBIT_1920x1080I << SHIFT_50, PS3AV_MODE_1080I50 }, 602 { PS3AV_RESBIT_SXGA << SHIFT_VESA, PS3AV_MODE_SXGA }, 603 { PS3AV_RESBIT_WXGA << SHIFT_VESA, PS3AV_MODE_WXGA }, 604 { PS3AV_RESBIT_1280x720P << SHIFT_60, PS3AV_MODE_720P60 }, 605 { PS3AV_RESBIT_1280x720P << SHIFT_50, PS3AV_MODE_720P50 }, 606 { PS3AV_RESBIT_720x480P << SHIFT_60, PS3AV_MODE_480P }, 607 { PS3AV_RESBIT_720x576P << SHIFT_50, PS3AV_MODE_576P }, 608 }; 609 610 static enum ps3av_mode_num ps3av_resbit2id(u32 res_50, u32 res_60, 611 u32 res_vesa) 612 { 613 unsigned int i; 614 u32 res_all; 615 616 /* 617 * We mask off the resolution bits we care about and combine the 618 * results in one bitfield, so make sure there's no overlap 619 */ 620 BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 & 621 PS3AV_RES_MASK_60 << SHIFT_60); 622 BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 & 623 PS3AV_RES_MASK_VESA << SHIFT_VESA); 624 BUILD_BUG_ON(PS3AV_RES_MASK_60 << SHIFT_60 & 625 PS3AV_RES_MASK_VESA << SHIFT_VESA); 626 res_all = (res_50 & PS3AV_RES_MASK_50) << SHIFT_50 | 627 (res_60 & PS3AV_RES_MASK_60) << SHIFT_60 | 628 (res_vesa & PS3AV_RES_MASK_VESA) << SHIFT_VESA; 629 630 if (!res_all) 631 return 0; 632 633 for (i = 0; i < ARRAY_SIZE(ps3av_preferred_modes); i++) 634 if (res_all & ps3av_preferred_modes[i].mask) 635 return ps3av_preferred_modes[i].id; 636 637 return 0; 638 } 639 640 static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info) 641 { 642 enum ps3av_mode_num id; 643 644 if (safe_mode) 645 return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; 646 647 /* check native resolution */ 648 id = ps3av_resbit2id(info->res_50.native, info->res_60.native, 649 info->res_vesa.native); 650 if (id) { 651 pr_debug("%s: Using native mode %d\n", __func__, id); 652 return id; 653 } 654 655 /* check supported resolutions */ 656 id = ps3av_resbit2id(info->res_50.res_bits, info->res_60.res_bits, 657 info->res_vesa.res_bits); 658 if (id) { 659 pr_debug("%s: Using supported mode %d\n", __func__, id); 660 return id; 661 } 662 663 if (ps3av->region & PS3AV_REGION_60) 664 id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; 665 else 666 id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_50; 667 pr_debug("%s: Using default mode %d\n", __func__, id); 668 return id; 669 } 670 671 static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) 672 { 673 const struct ps3av_info_monitor *info = &monitor_info->info; 674 const struct ps3av_info_audio *audio = info->audio; 675 char id[sizeof(info->monitor_id)*3+1]; 676 int i; 677 678 pr_debug("Monitor Info: size %u\n", monitor_info->send_hdr.size); 679 680 pr_debug("avport: %02x\n", info->avport); 681 for (i = 0; i < sizeof(info->monitor_id); i++) 682 sprintf(&id[i*3], " %02x", info->monitor_id[i]); 683 pr_debug("monitor_id: %s\n", id); 684 pr_debug("monitor_type: %02x\n", info->monitor_type); 685 pr_debug("monitor_name: %.*s\n", (int)sizeof(info->monitor_name), 686 info->monitor_name); 687 688 /* resolution */ 689 pr_debug("resolution_60: bits: %08x native: %08x\n", 690 info->res_60.res_bits, info->res_60.native); 691 pr_debug("resolution_50: bits: %08x native: %08x\n", 692 info->res_50.res_bits, info->res_50.native); 693 pr_debug("resolution_other: bits: %08x native: %08x\n", 694 info->res_other.res_bits, info->res_other.native); 695 pr_debug("resolution_vesa: bits: %08x native: %08x\n", 696 info->res_vesa.res_bits, info->res_vesa.native); 697 698 /* color space */ 699 pr_debug("color space rgb: %02x\n", info->cs.rgb); 700 pr_debug("color space yuv444: %02x\n", info->cs.yuv444); 701 pr_debug("color space yuv422: %02x\n", info->cs.yuv422); 702 703 /* color info */ 704 pr_debug("color info red: X %04x Y %04x\n", info->color.red_x, 705 info->color.red_y); 706 pr_debug("color info green: X %04x Y %04x\n", info->color.green_x, 707 info->color.green_y); 708 pr_debug("color info blue: X %04x Y %04x\n", info->color.blue_x, 709 info->color.blue_y); 710 pr_debug("color info white: X %04x Y %04x\n", info->color.white_x, 711 info->color.white_y); 712 pr_debug("color info gamma: %08x\n", info->color.gamma); 713 714 /* other info */ 715 pr_debug("supported_AI: %02x\n", info->supported_ai); 716 pr_debug("speaker_info: %02x\n", info->speaker_info); 717 pr_debug("num of audio: %02x\n", info->num_of_audio_block); 718 719 /* audio block */ 720 for (i = 0; i < info->num_of_audio_block; i++) { 721 pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: " 722 "%02x\n", 723 i, audio->type, audio->max_num_of_ch, audio->fs, 724 audio->sbit); 725 audio++; 726 } 727 } 728 729 static const struct ps3av_monitor_quirk { 730 const char *monitor_name; 731 u32 clear_60; 732 } ps3av_monitor_quirks[] = { 733 { 734 .monitor_name = "DELL 2007WFP", 735 .clear_60 = PS3AV_RESBIT_1920x1080I 736 }, { 737 .monitor_name = "L226WTQ", 738 .clear_60 = PS3AV_RESBIT_1920x1080I | 739 PS3AV_RESBIT_1920x1080P 740 }, { 741 .monitor_name = "SyncMaster", 742 .clear_60 = PS3AV_RESBIT_1920x1080I 743 } 744 }; 745 746 static void ps3av_fixup_monitor_info(struct ps3av_info_monitor *info) 747 { 748 unsigned int i; 749 const struct ps3av_monitor_quirk *quirk; 750 751 for (i = 0; i < ARRAY_SIZE(ps3av_monitor_quirks); i++) { 752 quirk = &ps3av_monitor_quirks[i]; 753 if (!strncmp(info->monitor_name, quirk->monitor_name, 754 sizeof(info->monitor_name))) { 755 pr_info("%s: Applying quirk for %s\n", __func__, 756 quirk->monitor_name); 757 info->res_60.res_bits &= ~quirk->clear_60; 758 info->res_60.native &= ~quirk->clear_60; 759 break; 760 } 761 } 762 } 763 764 static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf) 765 { 766 int i, res, id = 0, dvi = 0, rgb = 0; 767 struct ps3av_pkt_av_get_monitor_info monitor_info; 768 struct ps3av_info_monitor *info; 769 770 /* get mode id for hdmi */ 771 for (i = 0; i < av_hw_conf->num_of_hdmi && !id; i++) { 772 res = ps3av_cmd_video_get_monitor_info(&monitor_info, 773 PS3AV_CMD_AVPORT_HDMI_0 + 774 i); 775 if (res < 0) 776 return -1; 777 778 ps3av_monitor_info_dump(&monitor_info); 779 780 info = &monitor_info.info; 781 ps3av_fixup_monitor_info(info); 782 783 switch (info->monitor_type) { 784 case PS3AV_MONITOR_TYPE_DVI: 785 dvi = PS3AV_MODE_DVI; 786 /* fall through */ 787 case PS3AV_MONITOR_TYPE_HDMI: 788 id = ps3av_hdmi_get_id(info); 789 break; 790 } 791 } 792 793 if (!id) { 794 /* no HDMI interface or HDMI is off */ 795 if (ps3av->region & PS3AV_REGION_60) 796 id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60; 797 else 798 id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50; 799 if (ps3av->region & PS3AV_REGION_RGB) 800 rgb = PS3AV_MODE_RGB; 801 pr_debug("%s: Using avmulti mode %d\n", __func__, id); 802 } 803 804 return id | dvi | rgb; 805 } 806 807 static int ps3av_get_hw_conf(struct ps3av *ps3av) 808 { 809 int i, j, k, res; 810 const struct ps3av_pkt_av_get_hw_conf *hw_conf; 811 812 /* get av_hw_conf */ 813 res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf); 814 if (res < 0) 815 return -1; 816 817 hw_conf = &ps3av->av_hw_conf; 818 pr_debug("av_h_conf: num of hdmi: %u\n", hw_conf->num_of_hdmi); 819 pr_debug("av_h_conf: num of avmulti: %u\n", hw_conf->num_of_avmulti); 820 pr_debug("av_h_conf: num of spdif: %u\n", hw_conf->num_of_spdif); 821 822 for (i = 0; i < PS3AV_HEAD_MAX; i++) 823 ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i; 824 for (i = 0; i < PS3AV_OPT_PORT_MAX; i++) 825 ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i; 826 for (i = 0; i < hw_conf->num_of_hdmi; i++) 827 ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i; 828 for (j = 0; j < hw_conf->num_of_avmulti; j++) 829 ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j; 830 for (k = 0; k < hw_conf->num_of_spdif; k++) 831 ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k; 832 833 /* set all audio port */ 834 ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0 835 | PS3AV_CMD_AUDIO_PORT_HDMI_1 836 | PS3AV_CMD_AUDIO_PORT_AVMULTI_0 837 | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1; 838 839 return 0; 840 } 841 842 /* set mode using id */ 843 int ps3av_set_video_mode(u32 id) 844 { 845 int size; 846 u32 option; 847 848 size = ARRAY_SIZE(video_mode_table); 849 if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { 850 dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id); 851 return -EINVAL; 852 } 853 854 /* auto mode */ 855 option = id & ~PS3AV_MODE_MASK; 856 if ((id & PS3AV_MODE_MASK) == PS3AV_MODE_AUTO) { 857 id = ps3av_auto_videomode(&ps3av->av_hw_conf); 858 if (id < 1) { 859 printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); 860 return -EINVAL; 861 } 862 id |= option; 863 } 864 865 /* set videomode */ 866 wait_for_completion(&ps3av->done); 867 ps3av->ps3av_mode_old = ps3av->ps3av_mode; 868 ps3av->ps3av_mode = id; 869 if (ps3av_set_videomode()) 870 ps3av->ps3av_mode = ps3av->ps3av_mode_old; 871 872 return 0; 873 } 874 875 EXPORT_SYMBOL_GPL(ps3av_set_video_mode); 876 877 int ps3av_get_auto_mode(void) 878 { 879 return ps3av_auto_videomode(&ps3av->av_hw_conf); 880 } 881 882 EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); 883 884 int ps3av_get_mode(void) 885 { 886 return ps3av ? ps3av->ps3av_mode : 0; 887 } 888 889 EXPORT_SYMBOL_GPL(ps3av_get_mode); 890 891 /* get resolution by video_mode */ 892 int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) 893 { 894 int size; 895 896 id = id & PS3AV_MODE_MASK; 897 size = ARRAY_SIZE(video_mode_table); 898 if (id > size - 1 || id < 0) { 899 printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); 900 return -EINVAL; 901 } 902 *xres = video_mode_table[id].x; 903 *yres = video_mode_table[id].y; 904 return 0; 905 } 906 907 EXPORT_SYMBOL_GPL(ps3av_video_mode2res); 908 909 /* mute */ 910 int ps3av_video_mute(int mute) 911 { 912 return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON 913 : PS3AV_CMD_MUTE_OFF); 914 } 915 916 EXPORT_SYMBOL_GPL(ps3av_video_mute); 917 918 int ps3av_audio_mute(int mute) 919 { 920 return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON 921 : PS3AV_CMD_MUTE_OFF); 922 } 923 924 EXPORT_SYMBOL_GPL(ps3av_audio_mute); 925 926 void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), 927 void *flip_data) 928 { 929 mutex_lock(&ps3av->mutex); 930 ps3av->flip_ctl = flip_ctl; 931 ps3av->flip_data = flip_data; 932 mutex_unlock(&ps3av->mutex); 933 } 934 EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl); 935 936 void ps3av_flip_ctl(int on) 937 { 938 mutex_lock(&ps3av->mutex); 939 if (ps3av->flip_ctl) 940 ps3av->flip_ctl(on, ps3av->flip_data); 941 mutex_unlock(&ps3av->mutex); 942 } 943 944 static int ps3av_probe(struct ps3_system_bus_device *dev) 945 { 946 int res; 947 u32 id; 948 949 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); 950 dev_dbg(&dev->core, " timeout=%d\n", timeout); 951 952 if (ps3av) { 953 dev_err(&dev->core, "Only one ps3av device is supported\n"); 954 return -EBUSY; 955 } 956 957 ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL); 958 if (!ps3av) 959 return -ENOMEM; 960 961 mutex_init(&ps3av->mutex); 962 ps3av->ps3av_mode = PS3AV_MODE_AUTO; 963 ps3av->dev = dev; 964 965 INIT_WORK(&ps3av->work, ps3avd); 966 init_completion(&ps3av->done); 967 complete(&ps3av->done); 968 ps3av->wq = create_singlethread_workqueue("ps3avd"); 969 if (!ps3av->wq) 970 goto fail; 971 972 switch (ps3_os_area_get_av_multi_out()) { 973 case PS3_PARAM_AV_MULTI_OUT_NTSC: 974 ps3av->region = PS3AV_REGION_60; 975 break; 976 case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR: 977 case PS3_PARAM_AV_MULTI_OUT_SECAM: 978 ps3av->region = PS3AV_REGION_50; 979 break; 980 case PS3_PARAM_AV_MULTI_OUT_PAL_RGB: 981 ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB; 982 break; 983 default: 984 ps3av->region = PS3AV_REGION_60; 985 break; 986 } 987 988 /* init avsetting modules */ 989 res = ps3av_cmd_init(); 990 if (res < 0) 991 printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__, 992 res); 993 994 ps3av_get_hw_conf(ps3av); 995 996 #ifdef CONFIG_FB 997 if (fb_mode_option && !strcmp(fb_mode_option, "safe")) 998 safe_mode = 1; 999 #endif /* CONFIG_FB */ 1000 id = ps3av_auto_videomode(&ps3av->av_hw_conf); 1001 safe_mode = 0; 1002 1003 mutex_lock(&ps3av->mutex); 1004 ps3av->ps3av_mode = id; 1005 mutex_unlock(&ps3av->mutex); 1006 1007 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); 1008 1009 return 0; 1010 1011 fail: 1012 kfree(ps3av); 1013 ps3av = NULL; 1014 return -ENOMEM; 1015 } 1016 1017 static int ps3av_remove(struct ps3_system_bus_device *dev) 1018 { 1019 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); 1020 if (ps3av) { 1021 ps3av_cmd_fin(); 1022 if (ps3av->wq) 1023 destroy_workqueue(ps3av->wq); 1024 kfree(ps3av); 1025 ps3av = NULL; 1026 } 1027 1028 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); 1029 return 0; 1030 } 1031 1032 static void ps3av_shutdown(struct ps3_system_bus_device *dev) 1033 { 1034 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); 1035 ps3av_remove(dev); 1036 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); 1037 } 1038 1039 static struct ps3_vuart_port_driver ps3av_driver = { 1040 .core.match_id = PS3_MATCH_ID_AV_SETTINGS, 1041 .core.core.name = "ps3_av", 1042 .probe = ps3av_probe, 1043 .remove = ps3av_remove, 1044 .shutdown = ps3av_shutdown, 1045 }; 1046 1047 static int ps3av_module_init(void) 1048 { 1049 int error; 1050 1051 if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) 1052 return -ENODEV; 1053 1054 pr_debug(" -> %s:%d\n", __func__, __LINE__); 1055 1056 error = ps3_vuart_port_driver_register(&ps3av_driver); 1057 if (error) { 1058 printk(KERN_ERR 1059 "%s: ps3_vuart_port_driver_register failed %d\n", 1060 __func__, error); 1061 return error; 1062 } 1063 1064 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1065 return error; 1066 } 1067 1068 static void __exit ps3av_module_exit(void) 1069 { 1070 pr_debug(" -> %s:%d\n", __func__, __LINE__); 1071 ps3_vuart_port_driver_unregister(&ps3av_driver); 1072 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1073 } 1074 1075 subsys_initcall(ps3av_module_init); 1076 module_exit(ps3av_module_exit); 1077 1078 MODULE_LICENSE("GPL v2"); 1079 MODULE_DESCRIPTION("PS3 AV Settings Driver"); 1080 MODULE_AUTHOR("Sony Computer Entertainment Inc."); 1081 MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS); 1082