111227fd1SGeert Uytterhoeven /* 211227fd1SGeert Uytterhoeven * Copyright (C) 2006 Sony Computer Entertainment Inc. 311227fd1SGeert Uytterhoeven * Copyright 2006, 2007 Sony Corporation 411227fd1SGeert Uytterhoeven * 511227fd1SGeert Uytterhoeven * AV backend support for PS3 611227fd1SGeert Uytterhoeven * 711227fd1SGeert Uytterhoeven * This program is free software; you can redistribute it and/or modify it 811227fd1SGeert Uytterhoeven * under the terms of the GNU General Public License as published 911227fd1SGeert Uytterhoeven * by the Free Software Foundation; version 2 of the License. 1011227fd1SGeert Uytterhoeven * 1111227fd1SGeert Uytterhoeven * This program is distributed in the hope that it will be useful, but 1211227fd1SGeert Uytterhoeven * WITHOUT ANY WARRANTY; without even the implied warranty of 1311227fd1SGeert Uytterhoeven * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1411227fd1SGeert Uytterhoeven * General Public License for more details. 1511227fd1SGeert Uytterhoeven * 1611227fd1SGeert Uytterhoeven * You should have received a copy of the GNU General Public License along 1711227fd1SGeert Uytterhoeven * with this program; if not, write to the Free Software Foundation, Inc., 1811227fd1SGeert Uytterhoeven * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 1911227fd1SGeert Uytterhoeven */ 2011227fd1SGeert Uytterhoeven 2111227fd1SGeert Uytterhoeven #include <linux/module.h> 2211227fd1SGeert Uytterhoeven #include <linux/delay.h> 2311227fd1SGeert Uytterhoeven #include <linux/notifier.h> 2411227fd1SGeert Uytterhoeven #include <linux/reboot.h> 2511227fd1SGeert Uytterhoeven #include <linux/kernel.h> 2611227fd1SGeert Uytterhoeven #include <linux/ioctl.h> 2711227fd1SGeert Uytterhoeven #include <asm/lv1call.h> 2811227fd1SGeert Uytterhoeven #include <asm/ps3av.h> 2911227fd1SGeert Uytterhoeven #include <asm/ps3.h> 3011227fd1SGeert Uytterhoeven 3111227fd1SGeert Uytterhoeven #include "vuart.h" 3211227fd1SGeert Uytterhoeven 3311227fd1SGeert Uytterhoeven #define BUFSIZE 4096 /* vuart buf size */ 3411227fd1SGeert Uytterhoeven #define PS3AV_BUF_SIZE 512 /* max packet size */ 3511227fd1SGeert Uytterhoeven 3611227fd1SGeert Uytterhoeven static int timeout = 5000; /* in msec ( 5 sec ) */ 3711227fd1SGeert Uytterhoeven module_param(timeout, int, 0644); 3811227fd1SGeert Uytterhoeven 3911227fd1SGeert Uytterhoeven static struct ps3av ps3av; 4011227fd1SGeert Uytterhoeven 4111227fd1SGeert Uytterhoeven static struct ps3_vuart_port_device ps3av_dev = { 4211227fd1SGeert Uytterhoeven .match_id = PS3_MATCH_ID_AV_SETTINGS 4311227fd1SGeert Uytterhoeven }; 4411227fd1SGeert Uytterhoeven 4511227fd1SGeert Uytterhoeven /* color space */ 4611227fd1SGeert Uytterhoeven #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8 4711227fd1SGeert Uytterhoeven #define RGB8 PS3AV_CMD_VIDEO_CS_RGB_8 4811227fd1SGeert Uytterhoeven /* format */ 4911227fd1SGeert Uytterhoeven #define XRGB PS3AV_CMD_VIDEO_FMT_X8R8G8B8 5011227fd1SGeert Uytterhoeven /* aspect */ 5111227fd1SGeert Uytterhoeven #define A_N PS3AV_CMD_AV_ASPECT_4_3 5211227fd1SGeert Uytterhoeven #define A_W PS3AV_CMD_AV_ASPECT_16_9 5311227fd1SGeert Uytterhoeven static const struct avset_video_mode { 5411227fd1SGeert Uytterhoeven u32 cs; 5511227fd1SGeert Uytterhoeven u32 fmt; 5611227fd1SGeert Uytterhoeven u32 vid; 5711227fd1SGeert Uytterhoeven u32 aspect; 5811227fd1SGeert Uytterhoeven u32 x; 5911227fd1SGeert Uytterhoeven u32 y; 6011227fd1SGeert Uytterhoeven u32 interlace; 6111227fd1SGeert Uytterhoeven u32 freq; 6211227fd1SGeert Uytterhoeven } video_mode_table[] = { 6311227fd1SGeert Uytterhoeven { 0, }, /* auto */ 6411227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480, 1, 60}, 6511227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480, 0, 60}, 6611227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720, 0, 60}, 6711227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60}, 6811227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60}, 6911227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576, 1, 50}, 7011227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576, 0, 50}, 7111227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720, 0, 50}, 7211227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50}, 7311227fd1SGeert Uytterhoeven {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50}, 7411227fd1SGeert Uytterhoeven { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768, 0, 60}, 7511227fd1SGeert Uytterhoeven { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024, 0, 60}, 7611227fd1SGeert Uytterhoeven { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200, 0, 60}, 7711227fd1SGeert Uytterhoeven }; 7811227fd1SGeert Uytterhoeven 7911227fd1SGeert Uytterhoeven /* supported CIDs */ 8011227fd1SGeert Uytterhoeven static u32 cmd_table[] = { 8111227fd1SGeert Uytterhoeven /* init */ 8211227fd1SGeert Uytterhoeven PS3AV_CID_AV_INIT, 8311227fd1SGeert Uytterhoeven PS3AV_CID_AV_FIN, 8411227fd1SGeert Uytterhoeven PS3AV_CID_VIDEO_INIT, 8511227fd1SGeert Uytterhoeven PS3AV_CID_AUDIO_INIT, 8611227fd1SGeert Uytterhoeven 8711227fd1SGeert Uytterhoeven /* set */ 8811227fd1SGeert Uytterhoeven PS3AV_CID_AV_ENABLE_EVENT, 8911227fd1SGeert Uytterhoeven PS3AV_CID_AV_DISABLE_EVENT, 9011227fd1SGeert Uytterhoeven 9111227fd1SGeert Uytterhoeven PS3AV_CID_AV_VIDEO_CS, 9211227fd1SGeert Uytterhoeven PS3AV_CID_AV_VIDEO_MUTE, 9311227fd1SGeert Uytterhoeven PS3AV_CID_AV_VIDEO_DISABLE_SIG, 9411227fd1SGeert Uytterhoeven PS3AV_CID_AV_AUDIO_PARAM, 9511227fd1SGeert Uytterhoeven PS3AV_CID_AV_AUDIO_MUTE, 9611227fd1SGeert Uytterhoeven PS3AV_CID_AV_HDMI_MODE, 9711227fd1SGeert Uytterhoeven PS3AV_CID_AV_TV_MUTE, 9811227fd1SGeert Uytterhoeven 9911227fd1SGeert Uytterhoeven PS3AV_CID_VIDEO_MODE, 10011227fd1SGeert Uytterhoeven PS3AV_CID_VIDEO_FORMAT, 10111227fd1SGeert Uytterhoeven PS3AV_CID_VIDEO_PITCH, 10211227fd1SGeert Uytterhoeven 10311227fd1SGeert Uytterhoeven PS3AV_CID_AUDIO_MODE, 10411227fd1SGeert Uytterhoeven PS3AV_CID_AUDIO_MUTE, 10511227fd1SGeert Uytterhoeven PS3AV_CID_AUDIO_ACTIVE, 10611227fd1SGeert Uytterhoeven PS3AV_CID_AUDIO_INACTIVE, 10711227fd1SGeert Uytterhoeven PS3AV_CID_AVB_PARAM, 10811227fd1SGeert Uytterhoeven 10911227fd1SGeert Uytterhoeven /* get */ 11011227fd1SGeert Uytterhoeven PS3AV_CID_AV_GET_HW_CONF, 11111227fd1SGeert Uytterhoeven PS3AV_CID_AV_GET_MONITOR_INFO, 11211227fd1SGeert Uytterhoeven 11311227fd1SGeert Uytterhoeven /* event */ 11411227fd1SGeert Uytterhoeven PS3AV_CID_EVENT_UNPLUGGED, 11511227fd1SGeert Uytterhoeven PS3AV_CID_EVENT_PLUGGED, 11611227fd1SGeert Uytterhoeven PS3AV_CID_EVENT_HDCP_DONE, 11711227fd1SGeert Uytterhoeven PS3AV_CID_EVENT_HDCP_FAIL, 11811227fd1SGeert Uytterhoeven PS3AV_CID_EVENT_HDCP_AUTH, 11911227fd1SGeert Uytterhoeven PS3AV_CID_EVENT_HDCP_ERROR, 12011227fd1SGeert Uytterhoeven 12111227fd1SGeert Uytterhoeven 0 12211227fd1SGeert Uytterhoeven }; 12311227fd1SGeert Uytterhoeven 12411227fd1SGeert Uytterhoeven #define PS3AV_EVENT_CMD_MASK 0x10000000 12511227fd1SGeert Uytterhoeven #define PS3AV_EVENT_ID_MASK 0x0000ffff 12611227fd1SGeert Uytterhoeven #define PS3AV_CID_MASK 0xffffffff 12711227fd1SGeert Uytterhoeven #define PS3AV_REPLY_BIT 0x80000000 12811227fd1SGeert Uytterhoeven 12911227fd1SGeert Uytterhoeven #define ps3av_event_get_port_id(cid) ((cid >> 16) & 0xff) 13011227fd1SGeert Uytterhoeven 13111227fd1SGeert Uytterhoeven static u32 *ps3av_search_cmd_table(u32 cid, u32 mask) 13211227fd1SGeert Uytterhoeven { 13311227fd1SGeert Uytterhoeven u32 *table; 13411227fd1SGeert Uytterhoeven int i; 13511227fd1SGeert Uytterhoeven 13611227fd1SGeert Uytterhoeven table = cmd_table; 13711227fd1SGeert Uytterhoeven for (i = 0;; table++, i++) { 13811227fd1SGeert Uytterhoeven if ((*table & mask) == (cid & mask)) 13911227fd1SGeert Uytterhoeven break; 14011227fd1SGeert Uytterhoeven if (*table == 0) 14111227fd1SGeert Uytterhoeven return NULL; 14211227fd1SGeert Uytterhoeven } 14311227fd1SGeert Uytterhoeven return table; 14411227fd1SGeert Uytterhoeven } 14511227fd1SGeert Uytterhoeven 14611227fd1SGeert Uytterhoeven static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) 14711227fd1SGeert Uytterhoeven { 14811227fd1SGeert Uytterhoeven u32 *table; 14911227fd1SGeert Uytterhoeven 15011227fd1SGeert Uytterhoeven if (hdr->cid & PS3AV_EVENT_CMD_MASK) { 15111227fd1SGeert Uytterhoeven table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK); 15211227fd1SGeert Uytterhoeven if (table) 15311227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, 15411227fd1SGeert Uytterhoeven "recv event packet cid:%08x port:0x%x size:%d\n", 15511227fd1SGeert Uytterhoeven hdr->cid, ps3av_event_get_port_id(hdr->cid), 15611227fd1SGeert Uytterhoeven hdr->size); 15711227fd1SGeert Uytterhoeven else 15811227fd1SGeert Uytterhoeven printk(KERN_ERR 15911227fd1SGeert Uytterhoeven "%s: failed event packet, cid:%08x size:%d\n", 16011227fd1SGeert Uytterhoeven __FUNCTION__, hdr->cid, hdr->size); 16111227fd1SGeert Uytterhoeven return 1; /* receive event packet */ 16211227fd1SGeert Uytterhoeven } 16311227fd1SGeert Uytterhoeven return 0; 16411227fd1SGeert Uytterhoeven } 16511227fd1SGeert Uytterhoeven 16611227fd1SGeert Uytterhoeven static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, 16711227fd1SGeert Uytterhoeven struct ps3av_reply_hdr *recv_buf, int write_len, 16811227fd1SGeert Uytterhoeven int read_len) 16911227fd1SGeert Uytterhoeven { 17011227fd1SGeert Uytterhoeven int res; 17111227fd1SGeert Uytterhoeven u32 cmd; 17211227fd1SGeert Uytterhoeven int event; 17311227fd1SGeert Uytterhoeven 17411227fd1SGeert Uytterhoeven if (!ps3av.available) 17511227fd1SGeert Uytterhoeven return -ENODEV; 17611227fd1SGeert Uytterhoeven 17711227fd1SGeert Uytterhoeven /* send pkt */ 17811227fd1SGeert Uytterhoeven res = ps3av_vuart_write(ps3av.dev, send_buf, write_len); 17911227fd1SGeert Uytterhoeven if (res < 0) { 18011227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, 18111227fd1SGeert Uytterhoeven "%s: ps3av_vuart_write() failed (result=%d)\n", 18211227fd1SGeert Uytterhoeven __FUNCTION__, res); 18311227fd1SGeert Uytterhoeven return res; 18411227fd1SGeert Uytterhoeven } 18511227fd1SGeert Uytterhoeven 18611227fd1SGeert Uytterhoeven /* recv pkt */ 18711227fd1SGeert Uytterhoeven cmd = send_buf->cid; 18811227fd1SGeert Uytterhoeven do { 18911227fd1SGeert Uytterhoeven /* read header */ 19011227fd1SGeert Uytterhoeven res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE, 19111227fd1SGeert Uytterhoeven timeout); 19211227fd1SGeert Uytterhoeven if (res != PS3AV_HDR_SIZE) { 19311227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, 19411227fd1SGeert Uytterhoeven "%s: ps3av_vuart_read() failed (result=%d)\n", 19511227fd1SGeert Uytterhoeven __FUNCTION__, res); 19611227fd1SGeert Uytterhoeven return res; 19711227fd1SGeert Uytterhoeven } 19811227fd1SGeert Uytterhoeven 19911227fd1SGeert Uytterhoeven /* read body */ 20011227fd1SGeert Uytterhoeven res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid, 20111227fd1SGeert Uytterhoeven recv_buf->size, timeout); 20211227fd1SGeert Uytterhoeven if (res < 0) { 20311227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, 20411227fd1SGeert Uytterhoeven "%s: ps3av_vuart_read() failed (result=%d)\n", 20511227fd1SGeert Uytterhoeven __FUNCTION__, res); 20611227fd1SGeert Uytterhoeven return res; 20711227fd1SGeert Uytterhoeven } 20811227fd1SGeert Uytterhoeven res += PS3AV_HDR_SIZE; /* total len */ 20911227fd1SGeert Uytterhoeven event = ps3av_parse_event_packet(recv_buf); 21011227fd1SGeert Uytterhoeven /* ret > 0 event packet */ 21111227fd1SGeert Uytterhoeven } while (event); 21211227fd1SGeert Uytterhoeven 21311227fd1SGeert Uytterhoeven if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { 21411227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n", 21511227fd1SGeert Uytterhoeven __FUNCTION__, recv_buf->cid); 21611227fd1SGeert Uytterhoeven return -EINVAL; 21711227fd1SGeert Uytterhoeven } 21811227fd1SGeert Uytterhoeven 21911227fd1SGeert Uytterhoeven return 0; 22011227fd1SGeert Uytterhoeven } 22111227fd1SGeert Uytterhoeven 22211227fd1SGeert Uytterhoeven static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf, 22311227fd1SGeert Uytterhoeven const struct ps3av_reply_hdr *recv_buf, 22411227fd1SGeert Uytterhoeven int user_buf_size) 22511227fd1SGeert Uytterhoeven { 22611227fd1SGeert Uytterhoeven int return_len; 22711227fd1SGeert Uytterhoeven 22811227fd1SGeert Uytterhoeven if (recv_buf->version != PS3AV_VERSION) { 22911227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n", 23011227fd1SGeert Uytterhoeven recv_buf->version); 23111227fd1SGeert Uytterhoeven return -EFAULT; 23211227fd1SGeert Uytterhoeven } 23311227fd1SGeert Uytterhoeven return_len = recv_buf->size + PS3AV_HDR_SIZE; 23411227fd1SGeert Uytterhoeven if (return_len > user_buf_size) 23511227fd1SGeert Uytterhoeven return_len = user_buf_size; 23611227fd1SGeert Uytterhoeven memcpy(cmd_buf, recv_buf, return_len); 23711227fd1SGeert Uytterhoeven return 0; /* success */ 23811227fd1SGeert Uytterhoeven } 23911227fd1SGeert Uytterhoeven 24011227fd1SGeert Uytterhoeven void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr) 24111227fd1SGeert Uytterhoeven { 24211227fd1SGeert Uytterhoeven hdr->version = PS3AV_VERSION; 24311227fd1SGeert Uytterhoeven hdr->size = size - PS3AV_HDR_SIZE; 24411227fd1SGeert Uytterhoeven hdr->cid = cid; 24511227fd1SGeert Uytterhoeven } 24611227fd1SGeert Uytterhoeven 24711227fd1SGeert Uytterhoeven int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, 24811227fd1SGeert Uytterhoeven struct ps3av_send_hdr *buf) 24911227fd1SGeert Uytterhoeven { 25011227fd1SGeert Uytterhoeven int res = 0; 25111227fd1SGeert Uytterhoeven union { 25211227fd1SGeert Uytterhoeven struct ps3av_reply_hdr reply_hdr; 25311227fd1SGeert Uytterhoeven u8 raw[PS3AV_BUF_SIZE]; 25411227fd1SGeert Uytterhoeven } recv_buf; 25511227fd1SGeert Uytterhoeven 25611227fd1SGeert Uytterhoeven u32 *table; 25711227fd1SGeert Uytterhoeven 25811227fd1SGeert Uytterhoeven BUG_ON(!ps3av.available); 25911227fd1SGeert Uytterhoeven 26011227fd1SGeert Uytterhoeven if (down_interruptible(&ps3av.sem)) 26111227fd1SGeert Uytterhoeven return -ERESTARTSYS; 26211227fd1SGeert Uytterhoeven 26311227fd1SGeert Uytterhoeven table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); 26411227fd1SGeert Uytterhoeven BUG_ON(!table); 26511227fd1SGeert Uytterhoeven BUG_ON(send_len < PS3AV_HDR_SIZE); 26611227fd1SGeert Uytterhoeven BUG_ON(usr_buf_size < send_len); 26711227fd1SGeert Uytterhoeven BUG_ON(usr_buf_size > PS3AV_BUF_SIZE); 26811227fd1SGeert Uytterhoeven 26911227fd1SGeert Uytterhoeven /* create header */ 27011227fd1SGeert Uytterhoeven ps3av_set_hdr(cid, send_len, buf); 27111227fd1SGeert Uytterhoeven 27211227fd1SGeert Uytterhoeven /* send packet via vuart */ 27311227fd1SGeert Uytterhoeven res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len, 27411227fd1SGeert Uytterhoeven usr_buf_size); 27511227fd1SGeert Uytterhoeven if (res < 0) { 27611227fd1SGeert Uytterhoeven printk(KERN_ERR 27711227fd1SGeert Uytterhoeven "%s: ps3av_send_cmd_pkt() failed (result=%d)\n", 27811227fd1SGeert Uytterhoeven __FUNCTION__, res); 27911227fd1SGeert Uytterhoeven goto err; 28011227fd1SGeert Uytterhoeven } 28111227fd1SGeert Uytterhoeven 28211227fd1SGeert Uytterhoeven /* process reply packet */ 28311227fd1SGeert Uytterhoeven res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr, 28411227fd1SGeert Uytterhoeven usr_buf_size); 28511227fd1SGeert Uytterhoeven if (res < 0) { 28611227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", 28711227fd1SGeert Uytterhoeven __FUNCTION__, res); 28811227fd1SGeert Uytterhoeven goto err; 28911227fd1SGeert Uytterhoeven } 29011227fd1SGeert Uytterhoeven 29111227fd1SGeert Uytterhoeven up(&ps3av.sem); 29211227fd1SGeert Uytterhoeven return 0; 29311227fd1SGeert Uytterhoeven 29411227fd1SGeert Uytterhoeven err: 29511227fd1SGeert Uytterhoeven up(&ps3av.sem); 29611227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res); 29711227fd1SGeert Uytterhoeven return res; 29811227fd1SGeert Uytterhoeven } 29911227fd1SGeert Uytterhoeven 30011227fd1SGeert Uytterhoeven static int ps3av_set_av_video_mute(u32 mute) 30111227fd1SGeert Uytterhoeven { 30211227fd1SGeert Uytterhoeven int i, num_of_av_port, res; 30311227fd1SGeert Uytterhoeven 30411227fd1SGeert Uytterhoeven num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + 30511227fd1SGeert Uytterhoeven ps3av.av_hw_conf.num_of_avmulti; 30611227fd1SGeert Uytterhoeven /* video mute on */ 30711227fd1SGeert Uytterhoeven for (i = 0; i < num_of_av_port; i++) { 30811227fd1SGeert Uytterhoeven res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute); 30911227fd1SGeert Uytterhoeven if (res < 0) 31011227fd1SGeert Uytterhoeven return -1; 31111227fd1SGeert Uytterhoeven } 31211227fd1SGeert Uytterhoeven 31311227fd1SGeert Uytterhoeven return 0; 31411227fd1SGeert Uytterhoeven } 31511227fd1SGeert Uytterhoeven 31611227fd1SGeert Uytterhoeven static int ps3av_set_video_disable_sig(void) 31711227fd1SGeert Uytterhoeven { 31811227fd1SGeert Uytterhoeven int i, num_of_hdmi_port, num_of_av_port, res; 31911227fd1SGeert Uytterhoeven 32011227fd1SGeert Uytterhoeven num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi; 32111227fd1SGeert Uytterhoeven num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + 32211227fd1SGeert Uytterhoeven ps3av.av_hw_conf.num_of_avmulti; 32311227fd1SGeert Uytterhoeven 32411227fd1SGeert Uytterhoeven /* tv mute */ 32511227fd1SGeert Uytterhoeven for (i = 0; i < num_of_hdmi_port; i++) { 32611227fd1SGeert Uytterhoeven res = ps3av_cmd_av_tv_mute(ps3av.av_port[i], 32711227fd1SGeert Uytterhoeven PS3AV_CMD_MUTE_ON); 32811227fd1SGeert Uytterhoeven if (res < 0) 32911227fd1SGeert Uytterhoeven return -1; 33011227fd1SGeert Uytterhoeven } 33111227fd1SGeert Uytterhoeven msleep(100); 33211227fd1SGeert Uytterhoeven 33311227fd1SGeert Uytterhoeven /* video mute on */ 33411227fd1SGeert Uytterhoeven for (i = 0; i < num_of_av_port; i++) { 33511227fd1SGeert Uytterhoeven res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]); 33611227fd1SGeert Uytterhoeven if (res < 0) 33711227fd1SGeert Uytterhoeven return -1; 33811227fd1SGeert Uytterhoeven if (i < num_of_hdmi_port) { 33911227fd1SGeert Uytterhoeven res = ps3av_cmd_av_tv_mute(ps3av.av_port[i], 34011227fd1SGeert Uytterhoeven PS3AV_CMD_MUTE_OFF); 34111227fd1SGeert Uytterhoeven if (res < 0) 34211227fd1SGeert Uytterhoeven return -1; 34311227fd1SGeert Uytterhoeven } 34411227fd1SGeert Uytterhoeven } 34511227fd1SGeert Uytterhoeven msleep(300); 34611227fd1SGeert Uytterhoeven 34711227fd1SGeert Uytterhoeven return 0; 34811227fd1SGeert Uytterhoeven } 34911227fd1SGeert Uytterhoeven 35011227fd1SGeert Uytterhoeven static int ps3av_set_audio_mute(u32 mute) 35111227fd1SGeert Uytterhoeven { 35211227fd1SGeert Uytterhoeven int i, num_of_av_port, num_of_opt_port, res; 35311227fd1SGeert Uytterhoeven 35411227fd1SGeert Uytterhoeven num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + 35511227fd1SGeert Uytterhoeven ps3av.av_hw_conf.num_of_avmulti; 35611227fd1SGeert Uytterhoeven num_of_opt_port = ps3av.av_hw_conf.num_of_spdif; 35711227fd1SGeert Uytterhoeven 35811227fd1SGeert Uytterhoeven for (i = 0; i < num_of_av_port; i++) { 35911227fd1SGeert Uytterhoeven res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute); 36011227fd1SGeert Uytterhoeven if (res < 0) 36111227fd1SGeert Uytterhoeven return -1; 36211227fd1SGeert Uytterhoeven } 36311227fd1SGeert Uytterhoeven for (i = 0; i < num_of_opt_port; i++) { 36411227fd1SGeert Uytterhoeven res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute); 36511227fd1SGeert Uytterhoeven if (res < 0) 36611227fd1SGeert Uytterhoeven return -1; 36711227fd1SGeert Uytterhoeven } 36811227fd1SGeert Uytterhoeven 36911227fd1SGeert Uytterhoeven return 0; 37011227fd1SGeert Uytterhoeven } 37111227fd1SGeert Uytterhoeven 37211227fd1SGeert Uytterhoeven int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) 37311227fd1SGeert Uytterhoeven { 37411227fd1SGeert Uytterhoeven struct ps3av_pkt_avb_param avb_param; 37511227fd1SGeert Uytterhoeven int i, num_of_audio, vid, res; 37611227fd1SGeert Uytterhoeven struct ps3av_pkt_audio_mode audio_mode; 37711227fd1SGeert Uytterhoeven u32 len = 0; 37811227fd1SGeert Uytterhoeven 37911227fd1SGeert Uytterhoeven num_of_audio = ps3av.av_hw_conf.num_of_hdmi + 38011227fd1SGeert Uytterhoeven ps3av.av_hw_conf.num_of_avmulti + 38111227fd1SGeert Uytterhoeven ps3av.av_hw_conf.num_of_spdif; 38211227fd1SGeert Uytterhoeven 38311227fd1SGeert Uytterhoeven avb_param.num_of_video_pkt = 0; 38411227fd1SGeert Uytterhoeven avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */ 38511227fd1SGeert Uytterhoeven avb_param.num_of_av_video_pkt = 0; 38611227fd1SGeert Uytterhoeven avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi; 38711227fd1SGeert Uytterhoeven 38811227fd1SGeert Uytterhoeven vid = video_mode_table[ps3av.ps3av_mode].vid; 38911227fd1SGeert Uytterhoeven 39011227fd1SGeert Uytterhoeven /* audio mute */ 39111227fd1SGeert Uytterhoeven ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON); 39211227fd1SGeert Uytterhoeven 39311227fd1SGeert Uytterhoeven /* audio inactive */ 39411227fd1SGeert Uytterhoeven res = ps3av_cmd_audio_active(0, ps3av.audio_port); 39511227fd1SGeert Uytterhoeven if (res < 0) 39611227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, 39711227fd1SGeert Uytterhoeven "ps3av_cmd_audio_active OFF failed\n"); 39811227fd1SGeert Uytterhoeven 39911227fd1SGeert Uytterhoeven /* audio_pkt */ 40011227fd1SGeert Uytterhoeven for (i = 0; i < num_of_audio; i++) { 40111227fd1SGeert Uytterhoeven ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs, 40211227fd1SGeert Uytterhoeven word_bits, format, source); 40311227fd1SGeert Uytterhoeven if (i < ps3av.av_hw_conf.num_of_hdmi) { 40411227fd1SGeert Uytterhoeven /* hdmi only */ 40511227fd1SGeert Uytterhoeven len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len], 40611227fd1SGeert Uytterhoeven ps3av.av_port[i], 40711227fd1SGeert Uytterhoeven &audio_mode, vid); 40811227fd1SGeert Uytterhoeven } 40911227fd1SGeert Uytterhoeven /* audio_mode pkt should be sent separately */ 41011227fd1SGeert Uytterhoeven res = ps3av_cmd_audio_mode(&audio_mode); 41111227fd1SGeert Uytterhoeven if (res < 0) 41211227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, 41311227fd1SGeert Uytterhoeven "ps3av_cmd_audio_mode failed, port:%x\n", i); 41411227fd1SGeert Uytterhoeven } 41511227fd1SGeert Uytterhoeven 41611227fd1SGeert Uytterhoeven /* send command using avb pkt */ 41711227fd1SGeert Uytterhoeven len += offsetof(struct ps3av_pkt_avb_param, buf); 41811227fd1SGeert Uytterhoeven res = ps3av_cmd_avb_param(&avb_param, len); 41911227fd1SGeert Uytterhoeven if (res < 0) 42011227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); 42111227fd1SGeert Uytterhoeven 42211227fd1SGeert Uytterhoeven /* audio mute */ 42311227fd1SGeert Uytterhoeven ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF); 42411227fd1SGeert Uytterhoeven 42511227fd1SGeert Uytterhoeven /* audio active */ 42611227fd1SGeert Uytterhoeven res = ps3av_cmd_audio_active(1, ps3av.audio_port); 42711227fd1SGeert Uytterhoeven if (res < 0) 42811227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n"); 42911227fd1SGeert Uytterhoeven 43011227fd1SGeert Uytterhoeven return 0; 43111227fd1SGeert Uytterhoeven } 43211227fd1SGeert Uytterhoeven 43311227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_set_audio_mode); 43411227fd1SGeert Uytterhoeven 43511227fd1SGeert Uytterhoeven static int ps3av_set_videomode(void) 43611227fd1SGeert Uytterhoeven { 43711227fd1SGeert Uytterhoeven /* av video mute */ 43811227fd1SGeert Uytterhoeven ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); 43911227fd1SGeert Uytterhoeven 44011227fd1SGeert Uytterhoeven /* wake up ps3avd to do the actual video mode setting */ 44111227fd1SGeert Uytterhoeven up(&ps3av.ping); 44211227fd1SGeert Uytterhoeven 44311227fd1SGeert Uytterhoeven return 0; 44411227fd1SGeert Uytterhoeven } 44511227fd1SGeert Uytterhoeven 44611227fd1SGeert Uytterhoeven static void ps3av_set_videomode_cont(u32 id, u32 old_id) 44711227fd1SGeert Uytterhoeven { 44811227fd1SGeert Uytterhoeven struct ps3av_pkt_avb_param avb_param; 44911227fd1SGeert Uytterhoeven int i; 45011227fd1SGeert Uytterhoeven u32 len = 0, av_video_cs; 45111227fd1SGeert Uytterhoeven const struct avset_video_mode *video_mode; 45211227fd1SGeert Uytterhoeven int res; 45311227fd1SGeert Uytterhoeven 45411227fd1SGeert Uytterhoeven video_mode = &video_mode_table[id & PS3AV_MODE_MASK]; 45511227fd1SGeert Uytterhoeven 45611227fd1SGeert Uytterhoeven avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ 45711227fd1SGeert Uytterhoeven avb_param.num_of_audio_pkt = 0; 45811227fd1SGeert Uytterhoeven avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi + 45911227fd1SGeert Uytterhoeven ps3av.av_hw_conf.num_of_avmulti; 46011227fd1SGeert Uytterhoeven avb_param.num_of_av_audio_pkt = 0; 46111227fd1SGeert Uytterhoeven 46211227fd1SGeert Uytterhoeven /* video signal off */ 46311227fd1SGeert Uytterhoeven ps3av_set_video_disable_sig(); 46411227fd1SGeert Uytterhoeven 46511227fd1SGeert Uytterhoeven /* Retail PS3 product doesn't support this */ 46611227fd1SGeert Uytterhoeven if (id & PS3AV_MODE_HDCP_OFF) { 46711227fd1SGeert Uytterhoeven res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); 46811227fd1SGeert Uytterhoeven if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) 46911227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "Not supported\n"); 47011227fd1SGeert Uytterhoeven else if (res) 47111227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, 47211227fd1SGeert Uytterhoeven "ps3av_cmd_av_hdmi_mode failed\n"); 47311227fd1SGeert Uytterhoeven } else if (old_id & PS3AV_MODE_HDCP_OFF) { 47411227fd1SGeert Uytterhoeven res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); 47511227fd1SGeert Uytterhoeven if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) 47611227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, 47711227fd1SGeert Uytterhoeven "ps3av_cmd_av_hdmi_mode failed\n"); 47811227fd1SGeert Uytterhoeven } 47911227fd1SGeert Uytterhoeven 48011227fd1SGeert Uytterhoeven /* video_pkt */ 48111227fd1SGeert Uytterhoeven for (i = 0; i < avb_param.num_of_video_pkt; i++) 48211227fd1SGeert Uytterhoeven len += ps3av_cmd_set_video_mode(&avb_param.buf[len], 48311227fd1SGeert Uytterhoeven ps3av.head[i], video_mode->vid, 48411227fd1SGeert Uytterhoeven video_mode->fmt, id); 48511227fd1SGeert Uytterhoeven /* av_video_pkt */ 48611227fd1SGeert Uytterhoeven for (i = 0; i < avb_param.num_of_av_video_pkt; i++) { 48711227fd1SGeert Uytterhoeven if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB) 48811227fd1SGeert Uytterhoeven av_video_cs = RGB8; 48911227fd1SGeert Uytterhoeven else 49011227fd1SGeert Uytterhoeven av_video_cs = video_mode->cs; 49111227fd1SGeert Uytterhoeven #ifndef PS3AV_HDMI_YUV 49211227fd1SGeert Uytterhoeven if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || 49311227fd1SGeert Uytterhoeven ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) 49411227fd1SGeert Uytterhoeven av_video_cs = RGB8; /* use RGB for HDMI */ 49511227fd1SGeert Uytterhoeven #endif 49611227fd1SGeert Uytterhoeven len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], 49711227fd1SGeert Uytterhoeven ps3av.av_port[i], 49811227fd1SGeert Uytterhoeven video_mode->vid, av_video_cs, 49911227fd1SGeert Uytterhoeven video_mode->aspect, id); 50011227fd1SGeert Uytterhoeven } 50111227fd1SGeert Uytterhoeven /* send command using avb pkt */ 50211227fd1SGeert Uytterhoeven len += offsetof(struct ps3av_pkt_avb_param, buf); 50311227fd1SGeert Uytterhoeven res = ps3av_cmd_avb_param(&avb_param, len); 50411227fd1SGeert Uytterhoeven if (res == PS3AV_STATUS_NO_SYNC_HEAD) 50511227fd1SGeert Uytterhoeven printk(KERN_WARNING 50611227fd1SGeert Uytterhoeven "%s: Command failed. Please try your request again. \n", 50711227fd1SGeert Uytterhoeven __FUNCTION__); 50811227fd1SGeert Uytterhoeven else if (res) 50911227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); 51011227fd1SGeert Uytterhoeven 51111227fd1SGeert Uytterhoeven msleep(1500); 51211227fd1SGeert Uytterhoeven /* av video mute */ 51311227fd1SGeert Uytterhoeven ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF); 51411227fd1SGeert Uytterhoeven } 51511227fd1SGeert Uytterhoeven 51611227fd1SGeert Uytterhoeven static int ps3avd(void *p) 51711227fd1SGeert Uytterhoeven { 51811227fd1SGeert Uytterhoeven struct ps3av *info = p; 51911227fd1SGeert Uytterhoeven 52011227fd1SGeert Uytterhoeven daemonize("ps3avd"); 52111227fd1SGeert Uytterhoeven while (1) { 52211227fd1SGeert Uytterhoeven down(&info->ping); 52311227fd1SGeert Uytterhoeven ps3av_set_videomode_cont(info->ps3av_mode, 52411227fd1SGeert Uytterhoeven info->ps3av_mode_old); 52511227fd1SGeert Uytterhoeven up(&info->pong); 52611227fd1SGeert Uytterhoeven } 52711227fd1SGeert Uytterhoeven return 0; 52811227fd1SGeert Uytterhoeven } 52911227fd1SGeert Uytterhoeven 53011227fd1SGeert Uytterhoeven static int ps3av_vid2table_id(int vid) 53111227fd1SGeert Uytterhoeven { 53211227fd1SGeert Uytterhoeven int i; 53311227fd1SGeert Uytterhoeven 53411227fd1SGeert Uytterhoeven for (i = 1; i < ARRAY_SIZE(video_mode_table); i++) 53511227fd1SGeert Uytterhoeven if (video_mode_table[i].vid == vid) 53611227fd1SGeert Uytterhoeven return i; 53711227fd1SGeert Uytterhoeven return -1; 53811227fd1SGeert Uytterhoeven } 53911227fd1SGeert Uytterhoeven 54011227fd1SGeert Uytterhoeven static int ps3av_resbit2vid(u32 res_50, u32 res_60) 54111227fd1SGeert Uytterhoeven { 54211227fd1SGeert Uytterhoeven int vid = -1; 54311227fd1SGeert Uytterhoeven 54411227fd1SGeert Uytterhoeven if (res_50 > res_60) { /* if res_50 == res_60, res_60 will be used */ 54511227fd1SGeert Uytterhoeven if (res_50 & PS3AV_RESBIT_1920x1080P) 54611227fd1SGeert Uytterhoeven vid = PS3AV_CMD_VIDEO_VID_1080P_50HZ; 54711227fd1SGeert Uytterhoeven else if (res_50 & PS3AV_RESBIT_1920x1080I) 54811227fd1SGeert Uytterhoeven vid = PS3AV_CMD_VIDEO_VID_1080I_50HZ; 54911227fd1SGeert Uytterhoeven else if (res_50 & PS3AV_RESBIT_1280x720P) 55011227fd1SGeert Uytterhoeven vid = PS3AV_CMD_VIDEO_VID_720P_50HZ; 55111227fd1SGeert Uytterhoeven else if (res_50 & PS3AV_RESBIT_720x576P) 55211227fd1SGeert Uytterhoeven vid = PS3AV_CMD_VIDEO_VID_576P; 55311227fd1SGeert Uytterhoeven else 55411227fd1SGeert Uytterhoeven vid = -1; 55511227fd1SGeert Uytterhoeven } else { 55611227fd1SGeert Uytterhoeven if (res_60 & PS3AV_RESBIT_1920x1080P) 55711227fd1SGeert Uytterhoeven vid = PS3AV_CMD_VIDEO_VID_1080P_60HZ; 55811227fd1SGeert Uytterhoeven else if (res_60 & PS3AV_RESBIT_1920x1080I) 55911227fd1SGeert Uytterhoeven vid = PS3AV_CMD_VIDEO_VID_1080I_60HZ; 56011227fd1SGeert Uytterhoeven else if (res_60 & PS3AV_RESBIT_1280x720P) 56111227fd1SGeert Uytterhoeven vid = PS3AV_CMD_VIDEO_VID_720P_60HZ; 56211227fd1SGeert Uytterhoeven else if (res_60 & PS3AV_RESBIT_720x480P) 56311227fd1SGeert Uytterhoeven vid = PS3AV_CMD_VIDEO_VID_480P; 56411227fd1SGeert Uytterhoeven else 56511227fd1SGeert Uytterhoeven vid = -1; 56611227fd1SGeert Uytterhoeven } 56711227fd1SGeert Uytterhoeven return vid; 56811227fd1SGeert Uytterhoeven } 56911227fd1SGeert Uytterhoeven 57011227fd1SGeert Uytterhoeven static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info) 57111227fd1SGeert Uytterhoeven { 57211227fd1SGeert Uytterhoeven u32 res_50, res_60; 57311227fd1SGeert Uytterhoeven int vid = -1; 57411227fd1SGeert Uytterhoeven 57511227fd1SGeert Uytterhoeven if (info->monitor_type != PS3AV_MONITOR_TYPE_HDMI) 57611227fd1SGeert Uytterhoeven return -1; 57711227fd1SGeert Uytterhoeven 57811227fd1SGeert Uytterhoeven /* check native resolution */ 57911227fd1SGeert Uytterhoeven res_50 = info->res_50.native & PS3AV_RES_MASK_50; 58011227fd1SGeert Uytterhoeven res_60 = info->res_60.native & PS3AV_RES_MASK_60; 58111227fd1SGeert Uytterhoeven if (res_50 || res_60) { 58211227fd1SGeert Uytterhoeven vid = ps3av_resbit2vid(res_50, res_60); 58311227fd1SGeert Uytterhoeven return vid; 58411227fd1SGeert Uytterhoeven } 58511227fd1SGeert Uytterhoeven 58611227fd1SGeert Uytterhoeven /* check resolution */ 58711227fd1SGeert Uytterhoeven res_50 = info->res_50.res_bits & PS3AV_RES_MASK_50; 58811227fd1SGeert Uytterhoeven res_60 = info->res_60.res_bits & PS3AV_RES_MASK_60; 58911227fd1SGeert Uytterhoeven if (res_50 || res_60) { 59011227fd1SGeert Uytterhoeven vid = ps3av_resbit2vid(res_50, res_60); 59111227fd1SGeert Uytterhoeven return vid; 59211227fd1SGeert Uytterhoeven } 59311227fd1SGeert Uytterhoeven 59411227fd1SGeert Uytterhoeven if (ps3av.region & PS3AV_REGION_60) 59511227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_HDMI_VID_REG_60; 59611227fd1SGeert Uytterhoeven else 59711227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_HDMI_VID_REG_50; 59811227fd1SGeert Uytterhoeven return vid; 59911227fd1SGeert Uytterhoeven } 60011227fd1SGeert Uytterhoeven 60111227fd1SGeert Uytterhoeven static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf, 60211227fd1SGeert Uytterhoeven int boot) 60311227fd1SGeert Uytterhoeven { 60411227fd1SGeert Uytterhoeven int i, res, vid = -1, dvi = 0, rgb = 0; 60511227fd1SGeert Uytterhoeven struct ps3av_pkt_av_get_monitor_info monitor_info; 60611227fd1SGeert Uytterhoeven struct ps3av_info_monitor *info; 60711227fd1SGeert Uytterhoeven 60811227fd1SGeert Uytterhoeven /* get vid for hdmi */ 60911227fd1SGeert Uytterhoeven for (i = 0; i < av_hw_conf->num_of_hdmi; i++) { 61011227fd1SGeert Uytterhoeven res = ps3av_cmd_video_get_monitor_info(&monitor_info, 61111227fd1SGeert Uytterhoeven PS3AV_CMD_AVPORT_HDMI_0 + 61211227fd1SGeert Uytterhoeven i); 61311227fd1SGeert Uytterhoeven if (res < 0) 61411227fd1SGeert Uytterhoeven return -1; 61511227fd1SGeert Uytterhoeven 61611227fd1SGeert Uytterhoeven ps3av_cmd_av_monitor_info_dump(&monitor_info); 61711227fd1SGeert Uytterhoeven info = &monitor_info.info; 61811227fd1SGeert Uytterhoeven /* check DVI */ 61911227fd1SGeert Uytterhoeven if (info->monitor_type == PS3AV_MONITOR_TYPE_DVI) { 62011227fd1SGeert Uytterhoeven dvi = PS3AV_MODE_DVI; 62111227fd1SGeert Uytterhoeven break; 62211227fd1SGeert Uytterhoeven } 62311227fd1SGeert Uytterhoeven /* check HDMI */ 62411227fd1SGeert Uytterhoeven vid = ps3av_hdmi_get_vid(info); 62511227fd1SGeert Uytterhoeven if (vid != -1) { 62611227fd1SGeert Uytterhoeven /* got valid vid */ 62711227fd1SGeert Uytterhoeven break; 62811227fd1SGeert Uytterhoeven } 62911227fd1SGeert Uytterhoeven } 63011227fd1SGeert Uytterhoeven 63111227fd1SGeert Uytterhoeven if (dvi) { 63211227fd1SGeert Uytterhoeven /* DVI mode */ 63311227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_DVI_VID; 63411227fd1SGeert Uytterhoeven } else if (vid == -1) { 63511227fd1SGeert Uytterhoeven /* no HDMI interface or HDMI is off */ 63611227fd1SGeert Uytterhoeven if (ps3av.region & PS3AV_REGION_60) 63711227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60; 63811227fd1SGeert Uytterhoeven else 63911227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50; 64011227fd1SGeert Uytterhoeven if (ps3av.region & PS3AV_REGION_RGB) 64111227fd1SGeert Uytterhoeven rgb = PS3AV_MODE_RGB; 64211227fd1SGeert Uytterhoeven } else if (boot) { 64311227fd1SGeert Uytterhoeven /* HDMI: using DEFAULT HDMI_VID while booting up */ 64411227fd1SGeert Uytterhoeven info = &monitor_info.info; 64511227fd1SGeert Uytterhoeven if (ps3av.region & PS3AV_REGION_60) { 64611227fd1SGeert Uytterhoeven if (info->res_60.res_bits & PS3AV_RESBIT_720x480P) 64711227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_HDMI_VID_REG_60; 64811227fd1SGeert Uytterhoeven else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P) 64911227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_HDMI_VID_REG_50; 65011227fd1SGeert Uytterhoeven else { 65111227fd1SGeert Uytterhoeven /* default */ 65211227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_HDMI_VID_REG_60; 65311227fd1SGeert Uytterhoeven } 65411227fd1SGeert Uytterhoeven } else { 65511227fd1SGeert Uytterhoeven if (info->res_50.res_bits & PS3AV_RESBIT_720x576P) 65611227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_HDMI_VID_REG_50; 65711227fd1SGeert Uytterhoeven else if (info->res_60.res_bits & PS3AV_RESBIT_720x480P) 65811227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_HDMI_VID_REG_60; 65911227fd1SGeert Uytterhoeven else { 66011227fd1SGeert Uytterhoeven /* default */ 66111227fd1SGeert Uytterhoeven vid = PS3AV_DEFAULT_HDMI_VID_REG_50; 66211227fd1SGeert Uytterhoeven } 66311227fd1SGeert Uytterhoeven } 66411227fd1SGeert Uytterhoeven } 66511227fd1SGeert Uytterhoeven 66611227fd1SGeert Uytterhoeven return (ps3av_vid2table_id(vid) | dvi | rgb); 66711227fd1SGeert Uytterhoeven } 66811227fd1SGeert Uytterhoeven 66911227fd1SGeert Uytterhoeven static int ps3av_get_hw_conf(struct ps3av *ps3av) 67011227fd1SGeert Uytterhoeven { 67111227fd1SGeert Uytterhoeven int i, j, k, res; 67211227fd1SGeert Uytterhoeven 67311227fd1SGeert Uytterhoeven /* get av_hw_conf */ 67411227fd1SGeert Uytterhoeven res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf); 67511227fd1SGeert Uytterhoeven if (res < 0) 67611227fd1SGeert Uytterhoeven return -1; 67711227fd1SGeert Uytterhoeven 67811227fd1SGeert Uytterhoeven ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf); 67911227fd1SGeert Uytterhoeven 68011227fd1SGeert Uytterhoeven for (i = 0; i < PS3AV_HEAD_MAX; i++) 68111227fd1SGeert Uytterhoeven ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i; 68211227fd1SGeert Uytterhoeven for (i = 0; i < PS3AV_OPT_PORT_MAX; i++) 68311227fd1SGeert Uytterhoeven ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i; 68411227fd1SGeert Uytterhoeven for (i = 0; i < ps3av->av_hw_conf.num_of_hdmi; i++) 68511227fd1SGeert Uytterhoeven ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i; 68611227fd1SGeert Uytterhoeven for (j = 0; j < ps3av->av_hw_conf.num_of_avmulti; j++) 68711227fd1SGeert Uytterhoeven ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j; 68811227fd1SGeert Uytterhoeven for (k = 0; k < ps3av->av_hw_conf.num_of_spdif; k++) 68911227fd1SGeert Uytterhoeven ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k; 69011227fd1SGeert Uytterhoeven 69111227fd1SGeert Uytterhoeven /* set all audio port */ 69211227fd1SGeert Uytterhoeven ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0 69311227fd1SGeert Uytterhoeven | PS3AV_CMD_AUDIO_PORT_HDMI_1 69411227fd1SGeert Uytterhoeven | PS3AV_CMD_AUDIO_PORT_AVMULTI_0 69511227fd1SGeert Uytterhoeven | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1; 69611227fd1SGeert Uytterhoeven 69711227fd1SGeert Uytterhoeven return 0; 69811227fd1SGeert Uytterhoeven } 69911227fd1SGeert Uytterhoeven 70011227fd1SGeert Uytterhoeven /* set mode using id */ 70111227fd1SGeert Uytterhoeven int ps3av_set_video_mode(u32 id, int boot) 70211227fd1SGeert Uytterhoeven { 70311227fd1SGeert Uytterhoeven int size; 70411227fd1SGeert Uytterhoeven u32 option; 70511227fd1SGeert Uytterhoeven 70611227fd1SGeert Uytterhoeven size = ARRAY_SIZE(video_mode_table); 70711227fd1SGeert Uytterhoeven if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { 70811227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __FUNCTION__, 70911227fd1SGeert Uytterhoeven id); 71011227fd1SGeert Uytterhoeven return -EINVAL; 71111227fd1SGeert Uytterhoeven } 71211227fd1SGeert Uytterhoeven 71311227fd1SGeert Uytterhoeven /* auto mode */ 71411227fd1SGeert Uytterhoeven option = id & ~PS3AV_MODE_MASK; 71511227fd1SGeert Uytterhoeven if ((id & PS3AV_MODE_MASK) == 0) { 71611227fd1SGeert Uytterhoeven id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot); 71711227fd1SGeert Uytterhoeven if (id < 1) { 71811227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__, 71911227fd1SGeert Uytterhoeven id); 72011227fd1SGeert Uytterhoeven return -EINVAL; 72111227fd1SGeert Uytterhoeven } 72211227fd1SGeert Uytterhoeven id |= option; 72311227fd1SGeert Uytterhoeven } 72411227fd1SGeert Uytterhoeven 72511227fd1SGeert Uytterhoeven /* set videomode */ 72611227fd1SGeert Uytterhoeven down(&ps3av.pong); 72711227fd1SGeert Uytterhoeven ps3av.ps3av_mode_old = ps3av.ps3av_mode; 72811227fd1SGeert Uytterhoeven ps3av.ps3av_mode = id; 72911227fd1SGeert Uytterhoeven if (ps3av_set_videomode()) 73011227fd1SGeert Uytterhoeven ps3av.ps3av_mode = ps3av.ps3av_mode_old; 73111227fd1SGeert Uytterhoeven 73211227fd1SGeert Uytterhoeven return 0; 73311227fd1SGeert Uytterhoeven } 73411227fd1SGeert Uytterhoeven 73511227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_set_video_mode); 73611227fd1SGeert Uytterhoeven 73711227fd1SGeert Uytterhoeven int ps3av_set_mode(u32 id, int boot) 73811227fd1SGeert Uytterhoeven { 73911227fd1SGeert Uytterhoeven int res; 74011227fd1SGeert Uytterhoeven 74111227fd1SGeert Uytterhoeven res = ps3av_set_video_mode(id, boot); 74211227fd1SGeert Uytterhoeven if (res) 74311227fd1SGeert Uytterhoeven return res; 74411227fd1SGeert Uytterhoeven 74511227fd1SGeert Uytterhoeven res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2, 74611227fd1SGeert Uytterhoeven PS3AV_CMD_AUDIO_FS_48K, 74711227fd1SGeert Uytterhoeven PS3AV_CMD_AUDIO_WORD_BITS_16, 74811227fd1SGeert Uytterhoeven PS3AV_CMD_AUDIO_FORMAT_PCM, 74911227fd1SGeert Uytterhoeven PS3AV_CMD_AUDIO_SOURCE_SERIAL); 75011227fd1SGeert Uytterhoeven if (res) 75111227fd1SGeert Uytterhoeven return res; 75211227fd1SGeert Uytterhoeven 75311227fd1SGeert Uytterhoeven return 0; 75411227fd1SGeert Uytterhoeven } 75511227fd1SGeert Uytterhoeven 75611227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_set_mode); 75711227fd1SGeert Uytterhoeven 75811227fd1SGeert Uytterhoeven int ps3av_get_mode(void) 75911227fd1SGeert Uytterhoeven { 76011227fd1SGeert Uytterhoeven return ps3av.ps3av_mode; 76111227fd1SGeert Uytterhoeven } 76211227fd1SGeert Uytterhoeven 76311227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_get_mode); 76411227fd1SGeert Uytterhoeven 76511227fd1SGeert Uytterhoeven int ps3av_get_scanmode(int id) 76611227fd1SGeert Uytterhoeven { 76711227fd1SGeert Uytterhoeven int size; 76811227fd1SGeert Uytterhoeven 76911227fd1SGeert Uytterhoeven id = id & PS3AV_MODE_MASK; 77011227fd1SGeert Uytterhoeven size = ARRAY_SIZE(video_mode_table); 77111227fd1SGeert Uytterhoeven if (id > size - 1 || id < 0) { 77211227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id); 77311227fd1SGeert Uytterhoeven return -EINVAL; 77411227fd1SGeert Uytterhoeven } 77511227fd1SGeert Uytterhoeven return video_mode_table[id].interlace; 77611227fd1SGeert Uytterhoeven } 77711227fd1SGeert Uytterhoeven 77811227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_get_scanmode); 77911227fd1SGeert Uytterhoeven 78011227fd1SGeert Uytterhoeven int ps3av_get_refresh_rate(int id) 78111227fd1SGeert Uytterhoeven { 78211227fd1SGeert Uytterhoeven int size; 78311227fd1SGeert Uytterhoeven 78411227fd1SGeert Uytterhoeven id = id & PS3AV_MODE_MASK; 78511227fd1SGeert Uytterhoeven size = ARRAY_SIZE(video_mode_table); 78611227fd1SGeert Uytterhoeven if (id > size - 1 || id < 0) { 78711227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id); 78811227fd1SGeert Uytterhoeven return -EINVAL; 78911227fd1SGeert Uytterhoeven } 79011227fd1SGeert Uytterhoeven return video_mode_table[id].freq; 79111227fd1SGeert Uytterhoeven } 79211227fd1SGeert Uytterhoeven 79311227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_get_refresh_rate); 79411227fd1SGeert Uytterhoeven 79511227fd1SGeert Uytterhoeven /* get resolution by video_mode */ 79611227fd1SGeert Uytterhoeven int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) 79711227fd1SGeert Uytterhoeven { 79811227fd1SGeert Uytterhoeven int size; 79911227fd1SGeert Uytterhoeven 80011227fd1SGeert Uytterhoeven id = id & PS3AV_MODE_MASK; 80111227fd1SGeert Uytterhoeven size = ARRAY_SIZE(video_mode_table); 80211227fd1SGeert Uytterhoeven if (id > size - 1 || id < 0) { 80311227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id); 80411227fd1SGeert Uytterhoeven return -EINVAL; 80511227fd1SGeert Uytterhoeven } 80611227fd1SGeert Uytterhoeven *xres = video_mode_table[id].x; 80711227fd1SGeert Uytterhoeven *yres = video_mode_table[id].y; 80811227fd1SGeert Uytterhoeven return 0; 80911227fd1SGeert Uytterhoeven } 81011227fd1SGeert Uytterhoeven 81111227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_video_mode2res); 81211227fd1SGeert Uytterhoeven 81311227fd1SGeert Uytterhoeven /* mute */ 81411227fd1SGeert Uytterhoeven int ps3av_video_mute(int mute) 81511227fd1SGeert Uytterhoeven { 81611227fd1SGeert Uytterhoeven return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON 81711227fd1SGeert Uytterhoeven : PS3AV_CMD_MUTE_OFF); 81811227fd1SGeert Uytterhoeven } 81911227fd1SGeert Uytterhoeven 82011227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_video_mute); 82111227fd1SGeert Uytterhoeven 82211227fd1SGeert Uytterhoeven int ps3av_audio_mute(int mute) 82311227fd1SGeert Uytterhoeven { 82411227fd1SGeert Uytterhoeven return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON 82511227fd1SGeert Uytterhoeven : PS3AV_CMD_MUTE_OFF); 82611227fd1SGeert Uytterhoeven } 82711227fd1SGeert Uytterhoeven 82811227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_audio_mute); 82911227fd1SGeert Uytterhoeven 83011227fd1SGeert Uytterhoeven int ps3av_dev_open(void) 83111227fd1SGeert Uytterhoeven { 83211227fd1SGeert Uytterhoeven int status = 0; 83311227fd1SGeert Uytterhoeven 83411227fd1SGeert Uytterhoeven mutex_lock(&ps3av.mutex); 83511227fd1SGeert Uytterhoeven if (!ps3av.open_count++) { 83611227fd1SGeert Uytterhoeven status = lv1_gpu_open(0); 83711227fd1SGeert Uytterhoeven if (status) { 83811227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: lv1_gpu_open failed %d\n", 83911227fd1SGeert Uytterhoeven __FUNCTION__, status); 84011227fd1SGeert Uytterhoeven ps3av.open_count--; 84111227fd1SGeert Uytterhoeven } 84211227fd1SGeert Uytterhoeven } 84311227fd1SGeert Uytterhoeven mutex_unlock(&ps3av.mutex); 84411227fd1SGeert Uytterhoeven 84511227fd1SGeert Uytterhoeven return status; 84611227fd1SGeert Uytterhoeven } 84711227fd1SGeert Uytterhoeven 84811227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_dev_open); 84911227fd1SGeert Uytterhoeven 85011227fd1SGeert Uytterhoeven int ps3av_dev_close(void) 85111227fd1SGeert Uytterhoeven { 85211227fd1SGeert Uytterhoeven int status = 0; 85311227fd1SGeert Uytterhoeven 85411227fd1SGeert Uytterhoeven mutex_lock(&ps3av.mutex); 85511227fd1SGeert Uytterhoeven if (ps3av.open_count <= 0) { 85611227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__); 85711227fd1SGeert Uytterhoeven status = -1; 85811227fd1SGeert Uytterhoeven } else if (!--ps3av.open_count) { 85911227fd1SGeert Uytterhoeven status = lv1_gpu_close(); 86011227fd1SGeert Uytterhoeven if (status) 86111227fd1SGeert Uytterhoeven printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n", 86211227fd1SGeert Uytterhoeven __FUNCTION__, status); 86311227fd1SGeert Uytterhoeven } 86411227fd1SGeert Uytterhoeven mutex_unlock(&ps3av.mutex); 86511227fd1SGeert Uytterhoeven 86611227fd1SGeert Uytterhoeven return status; 86711227fd1SGeert Uytterhoeven } 86811227fd1SGeert Uytterhoeven 86911227fd1SGeert Uytterhoeven EXPORT_SYMBOL_GPL(ps3av_dev_close); 87011227fd1SGeert Uytterhoeven 87111227fd1SGeert Uytterhoeven static int ps3av_probe(struct ps3_vuart_port_device *dev) 87211227fd1SGeert Uytterhoeven { 87311227fd1SGeert Uytterhoeven int res; 87411227fd1SGeert Uytterhoeven u32 id; 87511227fd1SGeert Uytterhoeven 87611227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "init ...\n"); 87711227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, " timeout=%d\n", timeout); 87811227fd1SGeert Uytterhoeven 87911227fd1SGeert Uytterhoeven memset(&ps3av, 0, sizeof(ps3av)); 88011227fd1SGeert Uytterhoeven 88111227fd1SGeert Uytterhoeven init_MUTEX(&ps3av.sem); 88211227fd1SGeert Uytterhoeven init_MUTEX_LOCKED(&ps3av.ping); 88311227fd1SGeert Uytterhoeven init_MUTEX(&ps3av.pong); 88411227fd1SGeert Uytterhoeven mutex_init(&ps3av.mutex); 88511227fd1SGeert Uytterhoeven ps3av.ps3av_mode = 0; 88611227fd1SGeert Uytterhoeven ps3av.dev = dev; 88711227fd1SGeert Uytterhoeven kernel_thread(ps3avd, &ps3av, CLONE_KERNEL); 88811227fd1SGeert Uytterhoeven 88911227fd1SGeert Uytterhoeven ps3av.available = 1; 89011227fd1SGeert Uytterhoeven switch (ps3_os_area_get_av_multi_out()) { 89111227fd1SGeert Uytterhoeven case PS3_PARAM_AV_MULTI_OUT_NTSC: 89211227fd1SGeert Uytterhoeven ps3av.region = PS3AV_REGION_60; 89311227fd1SGeert Uytterhoeven break; 89411227fd1SGeert Uytterhoeven case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR: 89511227fd1SGeert Uytterhoeven case PS3_PARAM_AV_MULTI_OUT_SECAM: 89611227fd1SGeert Uytterhoeven ps3av.region = PS3AV_REGION_50; 89711227fd1SGeert Uytterhoeven break; 89811227fd1SGeert Uytterhoeven case PS3_PARAM_AV_MULTI_OUT_PAL_RGB: 89911227fd1SGeert Uytterhoeven ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB; 90011227fd1SGeert Uytterhoeven break; 90111227fd1SGeert Uytterhoeven default: 90211227fd1SGeert Uytterhoeven ps3av.region = PS3AV_REGION_60; 90311227fd1SGeert Uytterhoeven break; 90411227fd1SGeert Uytterhoeven } 90511227fd1SGeert Uytterhoeven 90611227fd1SGeert Uytterhoeven /* init avsetting modules */ 90711227fd1SGeert Uytterhoeven res = ps3av_cmd_init(); 90811227fd1SGeert Uytterhoeven if (res < 0) 90911227fd1SGeert Uytterhoeven printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__, 91011227fd1SGeert Uytterhoeven res); 91111227fd1SGeert Uytterhoeven 91211227fd1SGeert Uytterhoeven ps3av_get_hw_conf(&ps3av); 91311227fd1SGeert Uytterhoeven id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1); 91411227fd1SGeert Uytterhoeven mutex_lock(&ps3av.mutex); 91511227fd1SGeert Uytterhoeven ps3av.ps3av_mode = id; 91611227fd1SGeert Uytterhoeven mutex_unlock(&ps3av.mutex); 91711227fd1SGeert Uytterhoeven 91811227fd1SGeert Uytterhoeven dev_dbg(&ps3av_dev.core, "init...done\n"); 91911227fd1SGeert Uytterhoeven 92011227fd1SGeert Uytterhoeven return 0; 92111227fd1SGeert Uytterhoeven } 92211227fd1SGeert Uytterhoeven 92311227fd1SGeert Uytterhoeven static int ps3av_remove(struct ps3_vuart_port_device *dev) 92411227fd1SGeert Uytterhoeven { 92511227fd1SGeert Uytterhoeven if (ps3av.available) { 92611227fd1SGeert Uytterhoeven ps3av_cmd_fin(); 92711227fd1SGeert Uytterhoeven ps3av.available = 0; 92811227fd1SGeert Uytterhoeven } 92911227fd1SGeert Uytterhoeven 93011227fd1SGeert Uytterhoeven return 0; 93111227fd1SGeert Uytterhoeven } 93211227fd1SGeert Uytterhoeven 93311227fd1SGeert Uytterhoeven static void ps3av_shutdown(struct ps3_vuart_port_device *dev) 93411227fd1SGeert Uytterhoeven { 93511227fd1SGeert Uytterhoeven ps3av_remove(dev); 93611227fd1SGeert Uytterhoeven } 93711227fd1SGeert Uytterhoeven 93811227fd1SGeert Uytterhoeven static struct ps3_vuart_port_driver ps3av_driver = { 93911227fd1SGeert Uytterhoeven .match_id = PS3_MATCH_ID_AV_SETTINGS, 94011227fd1SGeert Uytterhoeven .core = { 94111227fd1SGeert Uytterhoeven .name = "ps3_av", 94211227fd1SGeert Uytterhoeven }, 94311227fd1SGeert Uytterhoeven .probe = ps3av_probe, 94411227fd1SGeert Uytterhoeven .remove = ps3av_remove, 94511227fd1SGeert Uytterhoeven .shutdown = ps3av_shutdown, 94611227fd1SGeert Uytterhoeven }; 94711227fd1SGeert Uytterhoeven 94811227fd1SGeert Uytterhoeven static int ps3av_module_init(void) 94911227fd1SGeert Uytterhoeven { 95011227fd1SGeert Uytterhoeven int error = ps3_vuart_port_driver_register(&ps3av_driver); 95111227fd1SGeert Uytterhoeven if (error) { 95211227fd1SGeert Uytterhoeven printk(KERN_ERR 95311227fd1SGeert Uytterhoeven "%s: ps3_vuart_port_driver_register failed %d\n", 95411227fd1SGeert Uytterhoeven __FUNCTION__, error); 95511227fd1SGeert Uytterhoeven return error; 95611227fd1SGeert Uytterhoeven } 95711227fd1SGeert Uytterhoeven 95811227fd1SGeert Uytterhoeven error = ps3_vuart_port_device_register(&ps3av_dev); 95911227fd1SGeert Uytterhoeven if (error) 96011227fd1SGeert Uytterhoeven printk(KERN_ERR 96111227fd1SGeert Uytterhoeven "%s: ps3_vuart_port_device_register failed %d\n", 96211227fd1SGeert Uytterhoeven __FUNCTION__, error); 96311227fd1SGeert Uytterhoeven 96411227fd1SGeert Uytterhoeven return error; 96511227fd1SGeert Uytterhoeven } 96611227fd1SGeert Uytterhoeven 96711227fd1SGeert Uytterhoeven static void __exit ps3av_module_exit(void) 96811227fd1SGeert Uytterhoeven { 96911227fd1SGeert Uytterhoeven device_unregister(&ps3av_dev.core); 97011227fd1SGeert Uytterhoeven ps3_vuart_port_driver_unregister(&ps3av_driver); 97111227fd1SGeert Uytterhoeven } 97211227fd1SGeert Uytterhoeven 97311227fd1SGeert Uytterhoeven subsys_initcall(ps3av_module_init); 97411227fd1SGeert Uytterhoeven module_exit(ps3av_module_exit); 975