]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/pvrusb2/pvrusb2-hdw.c
V4L/DVB (5090): Pvrusb2: A patch to use ARRAY_SIZE macro when appropriate
[linux-2.6-omap-h63xx.git] / drivers / media / video / pvrusb2 / pvrusb2-hdw.c
index 2de595112224021c2444fc0d10711888b1a98cfc..1c79ce1e16c42638962cfe765664de23ab450758 100644 (file)
@@ -39,8 +39,6 @@
 
 #define TV_MIN_FREQ     55250000L
 #define TV_MAX_FREQ    850000000L
-#define RADIO_MIN_FREQ  87000000L
-#define RADIO_MAX_FREQ 108000000L
 
 struct usb_device_id pvr2_device_table[] = {
        [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
@@ -76,12 +74,10 @@ static const char *pvr2_client_29xxx[] = {
 
 static struct pvr2_string_table pvr2_client_lists[] = {
        [PVR2_HDW_TYPE_29XXX] = {
-               pvr2_client_29xxx,
-               sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
+               pvr2_client_29xxx, ARRAY_SIZE(pvr2_client_29xxx)
        },
        [PVR2_HDW_TYPE_24XXX] = {
-               pvr2_client_24xxx,
-               sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
+               pvr2_client_24xxx, ARRAY_SIZE(pvr2_client_24xxx)
        },
 };
 
@@ -94,7 +90,6 @@ static int procreload = 0;
 static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
 static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
 static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
-static int auto_mode_switch[PVR_NUM];
 static int init_pause_msec = 0;
 
 module_param(ctlchg, int, S_IRUGO|S_IWUSR);
@@ -112,8 +107,6 @@ module_param_array(video_std,    int, NULL, 0444);
 MODULE_PARM_DESC(video_std,"specify initial video standard");
 module_param_array(tolerance,    int, NULL, 0444);
 MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
-module_param_array(auto_mode_switch,    int, NULL, 0444);
-MODULE_PARM_DESC(auto_mode_switch,"Enable TV/Radio automatic mode switch based on freq");
 
 #define PVR2_CTL_WRITE_ENDPOINT  0x01
 #define PVR2_CTL_READ_ENDPOINT   0x81
@@ -217,7 +210,7 @@ static const struct pvr2_mpeg_ids mpeg_ids[] = {
                .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
        }
 };
-#define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
+#define MPEGDEF_COUNT ARRAY_SIZE(mpeg_ids)
 
 
 static const char *control_values_srate[] = {
@@ -264,7 +257,6 @@ static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
 static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
 static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
 static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
-static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
 static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw);
@@ -436,34 +428,48 @@ static void ctrl_cleardirty_input(struct pvr2_ctrl *cptr)
        cptr->hdw->input_dirty = 0;
 }
 
-static int ctrl_freq_check(struct pvr2_ctrl *cptr,int v)
-{
-       /* Both ranges are simultaneously considered legal, in order to
-          permit implicit mode switching, i.e. set a frequency in the
-          other range and the mode will switch */
-       return (((v >= RADIO_MIN_FREQ) && (v <= RADIO_MAX_FREQ)) ||
-               ((v >= TV_MIN_FREQ) && (v <= TV_MAX_FREQ)));
-}
 
 static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp)
 {
-       /* Actual maximum depends on radio/tv mode */
-       if (cptr->hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-               *vp = RADIO_MAX_FREQ;
-       } else {
+       unsigned long fv;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if (hdw->tuner_signal_stale) {
+               pvr2_i2c_core_status_poll(hdw);
+       }
+       fv = hdw->tuner_signal_info.rangehigh;
+       if (!fv) {
+               /* Safety fallback */
                *vp = TV_MAX_FREQ;
+               return 0;
+       }
+       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+               fv = (fv * 125) / 2;
+       } else {
+               fv = fv * 62500;
        }
+       *vp = fv;
        return 0;
 }
 
 static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp)
 {
-       /* Actual minimum depends on radio/tv mode */
-       if (cptr->hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-               *vp = RADIO_MIN_FREQ;
-       } else {
+       unsigned long fv;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if (hdw->tuner_signal_stale) {
+               pvr2_i2c_core_status_poll(hdw);
+       }
+       fv = hdw->tuner_signal_info.rangelow;
+       if (!fv) {
+               /* Safety fallback */
                *vp = TV_MIN_FREQ;
+               return 0;
+       }
+       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+               fv = (fv * 125) / 2;
+       } else {
+               fv = fv * 62500;
        }
+       *vp = fv;
        return 0;
 }
 
@@ -623,8 +629,32 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
 
 static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
 {
-       *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) &
-               PVR2_SIGNAL_OK) ? 1 : 0);
+       struct pvr2_hdw *hdw = cptr->hdw;
+       pvr2_i2c_core_status_poll(hdw);
+       *vp = hdw->tuner_signal_info.signal;
+       return 0;
+}
+
+static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       int val = 0;
+       unsigned int subchan;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       pvr2_i2c_core_status_poll(hdw);
+       subchan = hdw->tuner_signal_info.rxsubchans;
+       if (subchan & V4L2_TUNER_SUB_MONO) {
+               val |= (1 << V4L2_TUNER_MODE_MONO);
+       }
+       if (subchan & V4L2_TUNER_SUB_STEREO) {
+               val |= (1 << V4L2_TUNER_MODE_STEREO);
+       }
+       if (subchan & V4L2_TUNER_SUB_LANG1) {
+               val |= (1 << V4L2_TUNER_MODE_LANG1);
+       }
+       if (subchan & V4L2_TUNER_SUB_LANG2) {
+               val |= (1 << V4L2_TUNER_MODE_LANG2);
+       }
+       *vp = val;
        return 0;
 }
 
@@ -734,7 +764,6 @@ VCREATE_FUNCS(audiomode)
 VCREATE_FUNCS(res_hor)
 VCREATE_FUNCS(res_ver)
 VCREATE_FUNCS(srate)
-VCREATE_FUNCS(automodeswitch)
 
 /* Table definition of all controls which can be manipulated */
 static const struct pvr2_ctl_info control_defs[] = {
@@ -833,12 +862,6 @@ static const struct pvr2_ctl_info control_defs[] = {
                   depending on the standard. */
                .get_max_value = ctrl_vres_max_get,
                .get_min_value = ctrl_vres_min_get,
-       },{
-               .desc = "Automatic TV / Radio mode switch based on frequency",
-               .name = "auto_mode_switch",
-               .default_value = 0,
-               DEFREF(automodeswitch),
-               DEFBOOL,
        },{
                .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
                .default_value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
@@ -855,10 +878,9 @@ static const struct pvr2_ctl_info control_defs[] = {
                .get_value = ctrl_freq_get,
                .is_dirty = ctrl_freq_is_dirty,
                .clear_dirty = ctrl_freq_clear_dirty,
-               DEFINT(TV_MIN_FREQ,TV_MAX_FREQ),
+               DEFINT(0,0),
                /* Hook in check for input value (tv/radio) and adjust
                   max/min values accordingly */
-               .check_value = ctrl_freq_check,
                .get_max_value = ctrl_freq_max_get,
                .get_min_value = ctrl_freq_min_get,
        },{
@@ -872,10 +894,9 @@ static const struct pvr2_ctl_info control_defs[] = {
                .name = "freq_table_value",
                .set_value = ctrl_channelfreq_set,
                .get_value = ctrl_channelfreq_get,
-               DEFINT(TV_MIN_FREQ,TV_MAX_FREQ),
+               DEFINT(0,0),
                /* Hook in check for input value (tv/radio) and adjust
                   max/min values accordingly */
-               .check_value = ctrl_freq_check,
                .get_max_value = ctrl_freq_max_get,
                .get_min_value = ctrl_freq_min_get,
        },{
@@ -898,7 +919,20 @@ static const struct pvr2_ctl_info control_defs[] = {
                .desc = "Signal Present",
                .name = "signal_present",
                .get_value = ctrl_signal_get,
-               DEFBOOL,
+               DEFINT(0,65535),
+       },{
+               .desc = "Audio Modes Present",
+               .name = "audio_modes_present",
+               .get_value = ctrl_audio_modes_present_get,
+               /* For this type we "borrow" the V4L2_TUNER_MODE enum from
+                  v4l.  Nothing outside of this module cares about this,
+                  but I reuse it in order to also reuse the
+                  control_values_audiomode string table. */
+               DEFMASK(((1 << V4L2_TUNER_MODE_MONO)|
+                        (1 << V4L2_TUNER_MODE_STEREO)|
+                        (1 << V4L2_TUNER_MODE_LANG1)|
+                        (1 << V4L2_TUNER_MODE_LANG2)),
+                       control_values_audiomode),
        },{
                .desc = "Video Standards Available Mask",
                .name = "video_standard_mask_available",
@@ -948,7 +982,7 @@ static const struct pvr2_ctl_info control_defs[] = {
        }
 };
 
-#define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0]))
+#define CTRLDEF_COUNT ARRAY_SIZE(control_defs)
 
 
 const char *pvr2_config_get_name(enum pvr2_config cfg)
@@ -984,71 +1018,28 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
    driver-core side effects of this action. */
 void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
 {
-       int mode = 0;
-
-       /* If hdw->automodeswitch_val is set, then we do something clever:
-          Look at the desired frequency and see if it looks like FM or TV.
-          Execute a possible mode switch based on this result.  Otherwise
-          we use the current input setting to determine which frequency
-          register we need to adjust. */
-       if (hdw->automodeswitch_val) {
-               /* Note that since FM RADIO frequency range sits *inside*
-                  the TV spectrum that we must therefore check the radio
-                  range first... */
-               if ((val >= RADIO_MIN_FREQ) && (val <= RADIO_MAX_FREQ)) {
-                       mode = 1;
-               } else if ((val >= TV_MIN_FREQ) && (val <= TV_MAX_FREQ)) {
-                       mode = 2;
-               }
-       } else {
-               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-                       mode = 1;
-               } else {
-                       mode = 2;
-               }
-       }
-
-       switch (mode) {
-       case 1:
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
                if (hdw->freqSelector) {
                        /* Swing over to radio frequency selection */
                        hdw->freqSelector = 0;
                        hdw->freqDirty = !0;
                }
-               if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
-                       /* Force switch to radio mode */
-                       hdw->input_val = PVR2_CVAL_INPUT_RADIO;
-                       hdw->input_dirty = !0;
-               }
                if (hdw->freqValRadio != val) {
                        hdw->freqValRadio = val;
                        hdw->freqSlotRadio = 0;
-                       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-                               hdw->freqDirty = !0;
-                       }
+                       hdw->freqDirty = !0;
                }
-               break;
-       case 2:
+       } else {
                if (!(hdw->freqSelector)) {
                        /* Swing over to television frequency selection */
                        hdw->freqSelector = 1;
                        hdw->freqDirty = !0;
                }
-               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-                       /* Force switch to television mode */
-                       hdw->input_val = PVR2_CVAL_INPUT_TV;
-                       hdw->input_dirty = !0;
-               }
                if (hdw->freqValTelevision != val) {
                        hdw->freqValTelevision = val;
                        hdw->freqSlotTelevision = 0;
-                       if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
-                               hdw->freqDirty = !0;
-                       }
+                       hdw->freqDirty = !0;
                }
-               break;
-       default:
-               break;
        }
 }
 
@@ -1140,12 +1131,10 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
        };
        static const struct pvr2_string_table fw_file_defs[] = {
                [PVR2_HDW_TYPE_29XXX] = {
-                       fw_files_29xxx,
-                       sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
+                       fw_files_29xxx, ARRAY_SIZE(fw_files_29xxx)
                },
                [PVR2_HDW_TYPE_24XXX] = {
-                       fw_files_24xxx,
-                       sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]),
+                       fw_files_24xxx, ARRAY_SIZE(fw_files_24xxx)
                },
        };
        hdw->fw1_state = FW1_STATE_FAILED; // default result
@@ -1232,8 +1221,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
        trace_firmware("pvr2_upload_firmware2");
 
        ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
-                                  sizeof(fw_files)/sizeof(fw_files[0]),
-                                  fw_files);
+                                  ARRAY_SIZE(fw_files), fw_files);
        if (ret < 0) return ret;
        fwidx = ret;
        ret = 0;
@@ -1801,11 +1789,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
        /* 104.3 MHz, a usable FM station for my area */
        hdw->freqValRadio = 104300000L;
 
-       /* Default value for auto mode switch based on module option */
-       if ((hdw->unit_number >= 0) && (hdw->unit_number < PVR_NUM)) {
-               hdw->automodeswitch_val = auto_mode_switch[hdw->unit_number];
-       }
-
        // Do not use pvr2_reset_ctl_endpoints() here.  It is not
        // thread-safe against the normal pvr2_send_request() mechanism.
        // (We should make it thread safe).
@@ -1945,8 +1928,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        struct pvr2_ctl_info *ciptr;
 
        hdw_type = devid - pvr2_device_table;
-       if (hdw_type >=
-           sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) {
+       if (hdw_type >= ARRAY_SIZE(pvr2_device_names)) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "Bogus device type of %u reported",hdw_type);
                return NULL;
@@ -1957,6 +1939,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                   hdw,pvr2_device_names[hdw_type]);
        if (!hdw) goto fail;
        memset(hdw,0,sizeof(*hdw));
+       hdw->tuner_signal_stale = !0;
        cx2341x_fill_defaults(&hdw->enc_ctl_state);
 
        hdw->control_cnt = CTRLDEF_COUNT;
@@ -2179,9 +2162,6 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
                pvr2_stream_destroy(hdw->vid_stream);
                hdw->vid_stream = NULL;
        }
-       if (hdw->audio_stat) {
-               hdw->audio_stat->detach(hdw->audio_stat->ctxt);
-       }
        if (hdw->decoder_ctrl) {
                hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
        }
@@ -2407,10 +2387,9 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
                cptr = hdw->controls + idx;
                if (cptr->info->is_dirty == 0) continue;
                if (!cptr->info->is_dirty(cptr)) continue;
-               if (!commit_flag) {
-                       commit_flag = !0;
-               }
+               commit_flag = !0;
 
+               if (!(pvrusb2_debug & PVR2_TRACE_CTL)) continue;
                bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
                                 cptr->info->name);
                value = 0;
@@ -2547,34 +2526,6 @@ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
 }
 
 
-/* Return bit mask indicating signal status */
-static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
-{
-       unsigned int msk = 0;
-       switch (hdw->input_val) {
-       case PVR2_CVAL_INPUT_TV:
-       case PVR2_CVAL_INPUT_RADIO:
-               if (hdw->decoder_ctrl &&
-                   hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) {
-                       msk |= PVR2_SIGNAL_OK;
-                       if (hdw->audio_stat &&
-                           hdw->audio_stat->status(hdw->audio_stat->ctxt)) {
-                               if (hdw->flag_stereo) {
-                                       msk |= PVR2_SIGNAL_STEREO;
-                               }
-                               if (hdw->flag_bilingual) {
-                                       msk |= PVR2_SIGNAL_SAP;
-                               }
-                       }
-               }
-               break;
-       default:
-               msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO;
-       }
-       return msk;
-}
-
-
 int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
 {
        int result;
@@ -2590,14 +2541,25 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
 }
 
 
-/* Return bit mask indicating signal status */
-unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw)
+/* Execute poll of tuner status */
+void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
 {
-       unsigned int msk = 0;
        LOCK_TAKE(hdw->big_lock); do {
-               msk = pvr2_hdw_get_signal_status_internal(hdw);
+               pvr2_i2c_core_status_poll(hdw);
        } while (0); LOCK_GIVE(hdw->big_lock);
-       return msk;
+}
+
+
+/* Return information about the tuner */
+int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               if (hdw->tuner_signal_stale) {
+                       pvr2_i2c_core_status_poll(hdw);
+               }
+               memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner));
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return 0;
 }