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