diff options
Diffstat (limited to 'drivers/ps3/ps3av.c')
| -rw-r--r-- | drivers/ps3/ps3av.c | 184 |
1 files changed, 74 insertions, 110 deletions
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c index 397f4ce849d..437fc35beb7 100644 --- a/drivers/ps3/ps3av.c +++ b/drivers/ps3/ps3av.c @@ -24,6 +24,7 @@ #include <linux/notifier.h> #include <linux/ioctl.h> #include <linux/fb.h> +#include <linux/slab.h> #include <asm/firmware.h> #include <asm/ps3av.h> @@ -59,8 +60,6 @@ static struct ps3av { struct ps3av_reply_hdr reply_hdr; u8 raw[PS3AV_BUF_SIZE]; } recv_buf; - void (*flip_ctl)(int on, void *data); - void *flip_data; } *ps3av; /* color space */ @@ -78,23 +77,21 @@ static const struct avset_video_mode { u32 aspect; u32 x; u32 y; - u32 interlace; - u32 freq; } video_mode_table[] = { { 0, }, /* auto */ - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480, 1, 60}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480, 0, 60}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720, 0, 60}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576, 1, 50}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576, 0, 50}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720, 0, 50}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50}, - {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50}, - { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768, 0, 60}, - { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024, 0, 60}, - { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200, 0, 60}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_W, 1280, 720}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_W, 1280, 720}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080}, + {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080}, + { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768}, + { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024}, + { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200}, }; /* supported CIDs */ @@ -341,7 +338,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, mutex_unlock(&ps3av->mutex); return 0; - err: +err: mutex_unlock(&ps3av->mutex); printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); return res; @@ -480,7 +477,6 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) return 0; } - EXPORT_SYMBOL_GPL(ps3av_set_audio_mode); static int ps3av_set_videomode(void) @@ -504,7 +500,7 @@ static void ps3av_set_videomode_packet(u32 id) video_mode = &video_mode_table[id & PS3AV_MODE_MASK]; - avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ + avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ avb_param.num_of_audio_pkt = 0; avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi + ps3av->av_hw_conf.num_of_avmulti; @@ -524,7 +520,7 @@ static void ps3av_set_videomode_packet(u32 id) #ifndef PS3AV_HDMI_YUV if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) - av_video_cs = RGB8; /* use RGB for HDMI */ + av_video_cs = RGB8; /* use RGB for HDMI */ #endif len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], ps3av->av_port[i], @@ -536,7 +532,7 @@ static void ps3av_set_videomode_packet(u32 id) res = ps3av_cmd_avb_param(&avb_param, len); if (res == PS3AV_STATUS_NO_SYNC_HEAD) printk(KERN_WARNING - "%s: Command failed. Please try your request again. \n", + "%s: Command failed. Please try your request again.\n", __func__); else if (res) dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); @@ -544,7 +540,7 @@ static void ps3av_set_videomode_packet(u32 id) static void ps3av_set_videomode_cont(u32 id, u32 old_id) { - static int vesa = 0; + static int vesa; int res; /* video signal off */ @@ -554,9 +550,9 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) * AV backend needs non-VESA mode setting at least one time * when VESA mode is used. */ - if (vesa == 0 && (id & PS3AV_MODE_MASK) >= 11) { + if (vesa == 0 && (id & PS3AV_MODE_MASK) >= PS3AV_MODE_WXGA) { /* vesa mode */ - ps3av_set_videomode_packet(2); /* 480P */ + ps3av_set_videomode_packet(PS3AV_MODE_480P); } vesa = 1; @@ -593,23 +589,24 @@ static void ps3avd(struct work_struct *work) #define SHIFT_VESA 8 static const struct { - unsigned mask : 19; - unsigned id : 4; + unsigned mask:19; + unsigned id:4; } ps3av_preferred_modes[] = { - { .mask = PS3AV_RESBIT_WUXGA << SHIFT_VESA, .id = 13 }, - { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_60, .id = 5 }, - { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_50, .id = 10 }, - { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_60, .id = 4 }, - { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_50, .id = 9 }, - { .mask = PS3AV_RESBIT_SXGA << SHIFT_VESA, .id = 12 }, - { .mask = PS3AV_RESBIT_WXGA << SHIFT_VESA, .id = 11 }, - { .mask = PS3AV_RESBIT_1280x720P << SHIFT_60, .id = 3 }, - { .mask = PS3AV_RESBIT_1280x720P << SHIFT_50, .id = 8 }, - { .mask = PS3AV_RESBIT_720x480P << SHIFT_60, .id = 2 }, - { .mask = PS3AV_RESBIT_720x576P << SHIFT_50, .id = 7 }, + { PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA }, + { PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 }, + { PS3AV_RESBIT_1920x1080P << SHIFT_50, PS3AV_MODE_1080P50 }, + { PS3AV_RESBIT_1920x1080I << SHIFT_60, PS3AV_MODE_1080I60 }, + { PS3AV_RESBIT_1920x1080I << SHIFT_50, PS3AV_MODE_1080I50 }, + { PS3AV_RESBIT_SXGA << SHIFT_VESA, PS3AV_MODE_SXGA }, + { PS3AV_RESBIT_WXGA << SHIFT_VESA, PS3AV_MODE_WXGA }, + { PS3AV_RESBIT_1280x720P << SHIFT_60, PS3AV_MODE_720P60 }, + { PS3AV_RESBIT_1280x720P << SHIFT_50, PS3AV_MODE_720P50 }, + { PS3AV_RESBIT_720x480P << SHIFT_60, PS3AV_MODE_480P }, + { PS3AV_RESBIT_720x576P << SHIFT_50, PS3AV_MODE_576P }, }; -static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa) +static enum ps3av_mode_num ps3av_resbit2id(u32 res_50, u32 res_60, + u32 res_vesa) { unsigned int i; u32 res_all; @@ -638,9 +635,9 @@ static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa) return 0; } -static int ps3av_hdmi_get_id(struct ps3av_info_monitor *info) +static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info) { - int id; + enum ps3av_mode_num id; if (safe_mode) return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; @@ -669,7 +666,8 @@ static int ps3av_hdmi_get_id(struct ps3av_info_monitor *info) return id; } -static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) +static void ps3av_monitor_info_dump( + const struct ps3av_pkt_av_get_monitor_info *monitor_info) { const struct ps3av_info_monitor *info = &monitor_info->info; const struct ps3av_info_audio *audio = info->audio; @@ -719,8 +717,8 @@ static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info * /* audio block */ for (i = 0; i < info->num_of_audio_block; i++) { - pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: " - "%02x\n", + pr_debug( + "audio[%d] type: %02x max_ch: %02x fs: %02x sbit: %02x\n", i, audio->type, audio->max_num_of_ch, audio->fs, audio->sbit); audio++; @@ -729,7 +727,7 @@ static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info * static const struct ps3av_monitor_quirk { const char *monitor_name; - u32 clear_60, clear_50, clear_vesa; + u32 clear_60; } ps3av_monitor_quirks[] = { { .monitor_name = "DELL 2007WFP", @@ -757,10 +755,6 @@ static void ps3av_fixup_monitor_info(struct ps3av_info_monitor *info) quirk->monitor_name); info->res_60.res_bits &= ~quirk->clear_60; info->res_60.native &= ~quirk->clear_60; - info->res_50.res_bits &= ~quirk->clear_50; - info->res_50.native &= ~quirk->clear_50; - info->res_vesa.res_bits &= ~quirk->clear_vesa; - info->res_vesa.native &= ~quirk->clear_vesa; break; } } @@ -845,7 +839,7 @@ static int ps3av_get_hw_conf(struct ps3av *ps3av) } /* set mode using id */ -int ps3av_set_video_mode(u32 id) +int ps3av_set_video_mode(int id) { int size; u32 option; @@ -858,7 +852,7 @@ int ps3av_set_video_mode(u32 id) /* auto mode */ option = id & ~PS3AV_MODE_MASK; - if ((id & PS3AV_MODE_MASK) == 0) { + if ((id & PS3AV_MODE_MASK) == PS3AV_MODE_AUTO) { id = ps3av_auto_videomode(&ps3av->av_hw_conf); if (id < 1) { printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); @@ -876,53 +870,20 @@ int ps3av_set_video_mode(u32 id) return 0; } - EXPORT_SYMBOL_GPL(ps3av_set_video_mode); int ps3av_get_auto_mode(void) { return ps3av_auto_videomode(&ps3av->av_hw_conf); } - EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); int ps3av_get_mode(void) { return ps3av ? ps3av->ps3av_mode : 0; } - EXPORT_SYMBOL_GPL(ps3av_get_mode); -int ps3av_get_scanmode(int id) -{ - int size; - - id = id & PS3AV_MODE_MASK; - size = ARRAY_SIZE(video_mode_table); - if (id > size - 1 || id < 0) { - printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); - return -EINVAL; - } - return video_mode_table[id].interlace; -} - -EXPORT_SYMBOL_GPL(ps3av_get_scanmode); - -int ps3av_get_refresh_rate(int id) -{ - int size; - - id = id & PS3AV_MODE_MASK; - size = ARRAY_SIZE(video_mode_table); - if (id > size - 1 || id < 0) { - printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); - return -EINVAL; - } - return video_mode_table[id].freq; -} - -EXPORT_SYMBOL_GPL(ps3av_get_refresh_rate); - /* get resolution by video_mode */ int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) { @@ -938,7 +899,6 @@ int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) *yres = video_mode_table[id].y; return 0; } - EXPORT_SYMBOL_GPL(ps3av_video_mode2res); /* mute */ @@ -947,39 +907,35 @@ int ps3av_video_mute(int mute) return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON : PS3AV_CMD_MUTE_OFF); } - EXPORT_SYMBOL_GPL(ps3av_video_mute); -int ps3av_audio_mute(int mute) +/* mute analog output only */ +int ps3av_audio_mute_analog(int mute) { - return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON - : PS3AV_CMD_MUTE_OFF); -} + int i, res; -EXPORT_SYMBOL_GPL(ps3av_audio_mute); - -void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), - void *flip_data) -{ - mutex_lock(&ps3av->mutex); - ps3av->flip_ctl = flip_ctl; - ps3av->flip_data = flip_data; - mutex_unlock(&ps3av->mutex); + for (i = 0; i < ps3av->av_hw_conf.num_of_avmulti; i++) { + res = ps3av_cmd_av_audio_mute(1, + &ps3av->av_port[i + ps3av->av_hw_conf.num_of_hdmi], + mute); + if (res < 0) + return -1; + } + return 0; } -EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl); +EXPORT_SYMBOL_GPL(ps3av_audio_mute_analog); -void ps3av_flip_ctl(int on) +int ps3av_audio_mute(int mute) { - mutex_lock(&ps3av->mutex); - if (ps3av->flip_ctl) - ps3av->flip_ctl(on, ps3av->flip_data); - mutex_unlock(&ps3av->mutex); + return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON + : PS3AV_CMD_MUTE_OFF); } +EXPORT_SYMBOL_GPL(ps3av_audio_mute); static int ps3av_probe(struct ps3_system_bus_device *dev) { int res; - u32 id; + int id; dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); dev_dbg(&dev->core, " timeout=%d\n", timeout); @@ -994,15 +950,17 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) return -ENOMEM; mutex_init(&ps3av->mutex); - ps3av->ps3av_mode = 0; + ps3av->ps3av_mode = PS3AV_MODE_AUTO; ps3av->dev = dev; INIT_WORK(&ps3av->work, ps3avd); init_completion(&ps3av->done); complete(&ps3av->done); ps3av->wq = create_singlethread_workqueue("ps3avd"); - if (!ps3av->wq) + if (!ps3av->wq) { + res = -ENOMEM; goto fail; + } switch (ps3_os_area_get_av_multi_out()) { case PS3_PARAM_AV_MULTI_OUT_NTSC: @@ -1033,6 +991,12 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) safe_mode = 1; #endif /* CONFIG_FB */ id = ps3av_auto_videomode(&ps3av->av_hw_conf); + if (id < 0) { + printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); + res = -EINVAL; + goto fail; + } + safe_mode = 0; mutex_lock(&ps3av->mutex); @@ -1046,7 +1010,7 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) fail: kfree(ps3av); ps3av = NULL; - return -ENOMEM; + return res; } static int ps3av_remove(struct ps3_system_bus_device *dev) @@ -1079,7 +1043,7 @@ static struct ps3_vuart_port_driver ps3av_driver = { .shutdown = ps3av_shutdown, }; -static int ps3av_module_init(void) +static int __init ps3av_module_init(void) { int error; |
