Hans Verkuil | 1a0adaf | 2007-04-27 12:31:25 -0300 | [diff] [blame^] | 1 | /* |
| 2 | saa7127 interface functions |
| 3 | Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> |
| 4 | |
| 5 | This program is free software; you can redistribute it and/or modify |
| 6 | it under the terms of the GNU General Public License as published by |
| 7 | the Free Software Foundation; either version 2 of the License, or |
| 8 | (at your option) any later version. |
| 9 | |
| 10 | This program is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | GNU General Public License for more details. |
| 14 | |
| 15 | You should have received a copy of the GNU General Public License |
| 16 | along with this program; if not, write to the Free Software |
| 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 18 | */ |
| 19 | |
| 20 | #include "ivtv-driver.h" |
| 21 | #include "ivtv-video.h" |
| 22 | #include "ivtv-i2c.h" |
| 23 | #include "ivtv-gpio.h" |
| 24 | #include "ivtv-cards.h" |
| 25 | #include <media/upd64031a.h> |
| 26 | #include <media/upd64083.h> |
| 27 | |
| 28 | void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3, |
| 29 | u8 vps4, u8 vps5) |
| 30 | { |
| 31 | struct v4l2_sliced_vbi_data data; |
| 32 | |
| 33 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
| 34 | return; |
| 35 | data.id = V4L2_SLICED_VPS; |
| 36 | data.field = 0; |
| 37 | data.line = enabled ? 16 : 0; |
| 38 | data.data[4] = vps1; |
| 39 | data.data[10] = vps2; |
| 40 | data.data[11] = vps3; |
| 41 | data.data[12] = vps4; |
| 42 | data.data[13] = vps5; |
| 43 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); |
| 44 | } |
| 45 | |
| 46 | void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4) |
| 47 | { |
| 48 | struct v4l2_sliced_vbi_data data; |
| 49 | |
| 50 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
| 51 | return; |
| 52 | data.id = V4L2_SLICED_CAPTION_525; |
| 53 | data.field = 0; |
| 54 | data.line = (mode & 1) ? 21 : 0; |
| 55 | data.data[0] = cc1; |
| 56 | data.data[1] = cc2; |
| 57 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); |
| 58 | data.field = 1; |
| 59 | data.line = (mode & 2) ? 21 : 0; |
| 60 | data.data[0] = cc3; |
| 61 | data.data[1] = cc4; |
| 62 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); |
| 63 | } |
| 64 | |
| 65 | void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) |
| 66 | { |
| 67 | struct v4l2_sliced_vbi_data data; |
| 68 | |
| 69 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
| 70 | return; |
| 71 | /* When using a 50 Hz system, always turn on the |
| 72 | wide screen signal with 4x3 ratio as the default. |
| 73 | Turning this signal on and off can confuse certain |
| 74 | TVs. As far as I can tell there is no reason not to |
| 75 | transmit this signal. */ |
| 76 | if ((itv->std & V4L2_STD_625_50) && !enabled) { |
| 77 | enabled = 1; |
| 78 | mode = 0x08; /* 4x3 full format */ |
| 79 | } |
| 80 | data.id = V4L2_SLICED_WSS_625; |
| 81 | data.field = 0; |
| 82 | data.line = enabled ? 23 : 0; |
| 83 | data.data[0] = mode & 0xff; |
| 84 | data.data[1] = (mode >> 8) & 0xff; |
| 85 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); |
| 86 | } |
| 87 | |
| 88 | void ivtv_encoder_enable(struct ivtv *itv, int enabled) |
| 89 | { |
| 90 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { |
| 91 | ivtv_saa7127(itv, enabled ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, |
| 92 | &enabled); |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | void ivtv_video_set_io(struct ivtv *itv) |
| 97 | { |
| 98 | struct v4l2_routing route; |
| 99 | int inp = itv->active_input; |
| 100 | u32 type; |
| 101 | |
| 102 | route.input = itv->card->video_inputs[inp].video_input; |
| 103 | route.output = 0; |
| 104 | itv->video_dec_func(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
| 105 | |
| 106 | type = itv->card->video_inputs[inp].video_type; |
| 107 | |
| 108 | if (type == IVTV_CARD_INPUT_VID_TUNER) { |
| 109 | route.input = 0; /* Tuner */ |
| 110 | } else if (type < IVTV_CARD_INPUT_COMPOSITE1) { |
| 111 | route.input = 2; /* S-Video */ |
| 112 | } else { |
| 113 | route.input = 1; /* Composite */ |
| 114 | } |
| 115 | |
| 116 | if (itv->card->hw_video & IVTV_HW_GPIO) |
| 117 | ivtv_gpio(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
| 118 | |
| 119 | if (itv->card->hw_video & IVTV_HW_UPD64031A) { |
| 120 | if (type == IVTV_CARD_INPUT_VID_TUNER || |
| 121 | type >= IVTV_CARD_INPUT_COMPOSITE1) { |
| 122 | /* Composite: GR on, connect to 3DYCS */ |
| 123 | route.input = UPD64031A_GR_ON | UPD64031A_3DYCS_COMPOSITE; |
| 124 | } else { |
| 125 | /* S-Video: GR bypassed, turn it off */ |
| 126 | route.input = UPD64031A_GR_OFF | UPD64031A_3DYCS_DISABLE; |
| 127 | } |
| 128 | route.input |= itv->card->gr_config; |
| 129 | |
| 130 | ivtv_upd64031a(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
| 131 | } |
| 132 | |
| 133 | if (itv->card->hw_video & IVTV_HW_UPD6408X) { |
| 134 | route.input = UPD64083_YCS_MODE; |
| 135 | if (type > IVTV_CARD_INPUT_VID_TUNER && |
| 136 | type < IVTV_CARD_INPUT_COMPOSITE1) { |
| 137 | /* S-Video uses YCNR mode and internal Y-ADC, the upd64031a |
| 138 | is not used. */ |
| 139 | route.input |= UPD64083_YCNR_MODE; |
| 140 | } |
| 141 | else if (itv->card->hw_video & IVTV_HW_UPD64031A) { |
| 142 | /* Use upd64031a output for tuner and composite(CX23416GYC only) inputs */ |
| 143 | if ((type == IVTV_CARD_INPUT_VID_TUNER)|| |
| 144 | (itv->card->type == IVTV_CARD_CX23416GYC)) { |
| 145 | route.input |= UPD64083_EXT_Y_ADC; |
| 146 | } |
| 147 | } |
| 148 | ivtv_upd64083(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
| 149 | } |
| 150 | } |