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