int sat;
        enum v4l2_chip_ident ident;
        u32 audclk_freq;
+       u32 crystal_freq;
+       u8 ucgc;
+       u8 cgcdiv;
+       u8 apll;
 };
 
 /* ----------------------------------------------------------------------- */
 };
 
 static const unsigned char saa7115_init_misc[] = {
-       0x38, 0x03,             /* audio stuff */
-       0x39, 0x10,
-       0x3a, 0x08,
-
        0x81, 0x01,             /* reg 0x15,0x16 define blanking window */
        0x82, 0x00,
        0x83, 0x01,             /* I port settings */
        u32 acni;
        u32 hz;
        u64 f;
+       u8 acc = 0;     /* reg 0x3a, audio clock control */
 
        v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
 
        if (freq < 32000 || freq > 48000)
                return -EINVAL;
 
+       /* The saa7113 has no audio clock */
+       if (state->ident == V4L2_IDENT_SAA7113)
+               return 0;
+
        /* hz is the refresh rate times 100 */
        hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
        /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
        acpf = (25600 * freq) / hz;
        /* acni = (256 * freq * 2^23) / crystal_frequency =
                  (freq * 2^(8+23)) / crystal_frequency =
-                 (freq << 31) / 32.11 MHz */
+                 (freq << 31) / crystal_frequency */
        f = freq;
        f = f << 31;
-       do_div(f, 32110000);
+       do_div(f, state->crystal_freq);
        acni = f;
+       if (state->ucgc) {
+               acpf = acpf * state->cgcdiv / 16;
+               acni = acni * state->cgcdiv / 16;
+               acc = 0x80;
+               if (state->cgcdiv == 3)
+                       acc |= 0x40;
+       }
+       if (state->apll)
+               acc |= 0x08;
 
+       saa7115_write(client, 0x38, 0x03);
+       saa7115_write(client, 0x39, 0x10);
+       saa7115_write(client, 0x3a, acc);
        saa7115_write(client, 0x30, acpf & 0xff);
        saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
        saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
                }
                break;
 
+       case VIDIOC_INT_S_CRYSTAL_FREQ:
+       {
+               struct v4l2_crystal_freq *freq = arg;
+
+               if (freq->freq != SAA7115_FREQ_32_11_MHZ &&
+                   freq->freq != SAA7115_FREQ_24_576_MHZ)
+                       return -EINVAL;
+               state->crystal_freq = freq->freq;
+               state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
+               state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
+               state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
+               saa7115_set_audio_clock_freq(client, state->audclk_freq);
+               break;
+       }
+
        case VIDIOC_INT_DECODE_VBI_LINE:
                saa7115_decode_vbi_line(client, arg);
                break;
        v4l_dbg(1, debug, client, "writing init values\n");
 
        /* init to 60hz/48khz */
-       if (state->ident == V4L2_IDENT_SAA7113)
+       if (state->ident == V4L2_IDENT_SAA7113) {
+               state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
                saa7115_writeregs(client, saa7113_init_auto_input);
-       else
+       } else {
+               state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
                saa7115_writeregs(client, saa7115_init_auto_input);
+       }
        saa7115_writeregs(client, saa7115_init_misc);
        saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
        saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
 
        [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)]  = "VIDIOC_INT_S_AUDIO_ROUTING",
        [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)]  = "VIDIOC_INT_G_AUDIO_ROUTING",
        [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)]  = "VIDIOC_INT_S_VIDEO_ROUTING",
-       [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING"
+       [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING",
+       [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)]   = "VIDIOC_INT_S_CRYSTAL_FREQ"
 };
 #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
 
                printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output);
                break;
        }
+       case VIDIOC_INT_S_CRYSTAL_FREQ:
+       {
+               struct v4l2_crystal_freq *p=arg;
+               printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags);
+               break;
+       }
        case VIDIOC_G_SLICED_VBI_CAP:
        {
                struct v4l2_sliced_vbi_cap *p=arg;
 
 /*
-    saa7115.h - definition for saa7113/4/5 inputs
+    saa7115.h - definition for saa7113/4/5 inputs and frequency flags
 
     Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
 
 #define SAA7115_SVIDEO2    8
 #define SAA7115_SVIDEO3    9
 
+/* SAA7115 v4l2_crystal_freq frequency values */
+#define SAA7115_FREQ_32_11_MHZ  32110000   /* 32.11 MHz crystal, SAA7114/5 only */
+#define SAA7115_FREQ_24_576_MHZ 24576000   /* 24.576 MHz crystal */
+
+/* SAA7115 v4l2_crystal_freq audio clock control flags */
+#define SAA7115_FREQ_FL_UCGC   (1 << 0)           /* SA 3A[7], UCGC, SAA7115 only */
+#define SAA7115_FREQ_FL_CGCDIV (1 << 1)           /* SA 3A[6], CGCDIV, SAA7115 only */
+#define SAA7115_FREQ_FL_APLL   (1 << 2)           /* SA 3A[3], APLL, SAA7114/5 only */
+
 #endif
 
 
 #define        VIDIOC_INT_S_VIDEO_ROUTING      _IOW ('d', 111, struct v4l2_routing)
 #define        VIDIOC_INT_G_VIDEO_ROUTING      _IOR ('d', 112, struct v4l2_routing)
 
+struct v4l2_crystal_freq {
+       u32 freq;       /* frequency in Hz of the crystal */
+       u32 flags;      /* device specific flags */
+};
+
+/* Sets the frequency of the crystal used to generate the clocks.
+   An extra flags field allows device specific configuration regarding
+   clock frequency dividers, etc. If not used, then set flags to 0.
+   If the frequency is not supported, then -EINVAL is returned. */
+#define VIDIOC_INT_S_CRYSTAL_FREQ      _IOW ('d', 113, struct v4l2_crystal_freq)
+
 #endif /* V4L2_COMMON_H_ */