diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi index d11ca6756..167ba576f 100644 --- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi @@ -1788,6 +1788,8 @@ vout_mux: vout_mux { compatible = "amlogic, vout_mux"; status = "okay"; + clocks = <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_VDIN_MEAS_GATE>; + clock-names = "fclk_div5", "vdin_meas_clk"; }; dummy_venc: dummy_venc { diff --git a/arch/arm64/boot/dts/amlogic/meson-s4d.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4d.dtsi index bab067611..d063254c3 100644 --- a/arch/arm64/boot/dts/amlogic/meson-s4d.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-s4d.dtsi @@ -1637,6 +1637,8 @@ vout_mux: vout_mux { compatible = "amlogic, vout_mux"; status = "okay"; + clocks = <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_VDIN_MEAS_GATE>; + clock-names = "fclk_div5", "vdin_meas_clk"; }; dummy_venc: dummy_venc { diff --git a/arch/arm64/boot/dts/amlogic/meson-sc2.dtsi b/arch/arm64/boot/dts/amlogic/meson-sc2.dtsi index e577aedd4..835d4145c 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sc2.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-sc2.dtsi @@ -1871,6 +1871,8 @@ vout_mux: vout_mux { compatible = "amlogic, vout_mux"; status = "okay"; + clocks = <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_VDIN_MEAS_GATE>; + clock-names = "fclk_div5", "vdin_meas_clk"; }; dummy_venc: dummy_venc { diff --git a/arch/arm64/boot/dts/amlogic/mesont3.dtsi b/arch/arm64/boot/dts/amlogic/mesont3.dtsi index 03cabaa96..3523cfaf4 100644 --- a/arch/arm64/boot/dts/amlogic/mesont3.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont3.dtsi @@ -1726,6 +1726,8 @@ vout_mux: vout_mux { compatible = "amlogic, vout_mux-t3"; status = "okay"; + clocks = <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_VDIN_MEAS>; + clock-names = "fclk_div5", "vdin_meas_clk"; }; vout: vout { diff --git a/arch/arm64/boot/dts/amlogic/mesont5m.dtsi b/arch/arm64/boot/dts/amlogic/mesont5m.dtsi index eb65dbbb4..4f6955ece 100644 --- a/arch/arm64/boot/dts/amlogic/mesont5m.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont5m.dtsi @@ -1598,6 +1598,8 @@ vout_mux: vout_mux { compatible = "amlogic, vout_mux-t5m"; status = "okay"; + clocks = <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_VDIN_MEAS>; + clock-names = "fclk_div5", "vdin_meas_clk"; }; vout: vout { diff --git a/arch/arm64/boot/dts/amlogic/mesont7.dtsi b/arch/arm64/boot/dts/amlogic/mesont7.dtsi index bd78a6d75..181305411 100644 --- a/arch/arm64/boot/dts/amlogic/mesont7.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont7.dtsi @@ -2739,6 +2739,8 @@ vout_mux: vout_mux { compatible = "amlogic, vout_mux-t7"; status = "okay"; + clocks = <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_VDIN_MEAS_GATE>; + clock-names = "fclk_div5", "vdin_meas_clk"; }; vout: vout { diff --git a/arch/arm64/boot/dts/amlogic/mesont7c.dtsi b/arch/arm64/boot/dts/amlogic/mesont7c.dtsi index 79e2b7088..2568f0f3d 100644 --- a/arch/arm64/boot/dts/amlogic/mesont7c.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont7c.dtsi @@ -2568,6 +2568,8 @@ vout_mux: vout_mux { compatible = "amlogic, vout_mux-t7"; status = "okay"; + clocks = <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_VDIN_MEAS_GATE>; + clock-names = "fclk_div5", "vdin_meas_clk"; }; vout: vout { diff --git a/drivers/media/enhancement/amvecm/frame_lock_policy.c b/drivers/media/enhancement/amvecm/frame_lock_policy.c index ee312bfa0..7391d56d2 100644 --- a/drivers/media/enhancement/amvecm/frame_lock_policy.c +++ b/drivers/media/enhancement/amvecm/frame_lock_policy.c @@ -73,7 +73,7 @@ unsigned int frame_lock_show_vout_framerate(void) unsigned int fr = 0; #ifdef CONFIG_AMLOGIC_VOUT_SERVE - fr = vout_frame_rate_measure(); + fr = vout_frame_rate_measure(1); #endif return fr; diff --git a/drivers/media/vin/tvin/vdin/vdin_drv.c b/drivers/media/vin/tvin/vdin/vdin_drv.c index 0d654ddd8..2a825fac8 100644 --- a/drivers/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/media/vin/tvin/vdin/vdin_drv.c @@ -419,7 +419,7 @@ static inline void vdin_get_in_out_fps(struct vdin_dev_s *devp) } /* get vout fps */ #ifdef CONFIG_AMLOGIC_VOUT_SERVE - vinfo_out_fps = vout_frame_rate_measure(); + vinfo_out_fps = vout_frame_rate_measure(1); #endif if (vinfo_out_fps != 0) { devp->vinfo_std_duration = vinfo_out_fps / 1000; diff --git a/drivers/media/vout/lcd/lcd_tcon.c b/drivers/media/vout/lcd/lcd_tcon.c index 6fde8ffd0..a92a6900a 100644 --- a/drivers/media/vout/lcd/lcd_tcon.c +++ b/drivers/media/vout/lcd/lcd_tcon.c @@ -1282,7 +1282,7 @@ static int lcd_tcon_data_multi_match_check(struct aml_lcd_drv_s *pdrv, case LCD_TCON_DATA_CTRL_MULTI_VFREQ_DIRECT: if (data_cnt != 2) goto lcd_tcon_data_multi_match_check_err_data_cnt; - temp = vout_frame_rate_measure(); //1000 multi + temp = vout_frame_rate_measure(1); //1000 multi if (temp == 0) temp = pdrv->config.timing.frame_rate; else @@ -1668,7 +1668,7 @@ int lcd_tcon_data_multi_set(struct aml_lcd_drv_s *pdrv, lcd_tcon_dbg_vsync_time_save(local_time[0], line_cnt, 0); } - temp = vout_frame_rate_measure(); //1000 multi + temp = vout_frame_rate_measure(1); //1000 multi if (temp == 0) temp = pdrv->config.timing.frame_rate; else diff --git a/drivers/media/vout/vout_serve/vout_mux.c b/drivers/media/vout/vout_serve/vout_mux.c index ffb17194d..d3ff4aabe 100644 --- a/drivers/media/vout/vout_serve/vout_mux.c +++ b/drivers/media/vout/vout_serve/vout_mux.c @@ -25,9 +25,11 @@ /* must be last include file */ #include +#define VDIN_MEAS_CLK_FREQ 50000000 //50MHz struct vout_mux_data_s { - int vdin_meas_id; - unsigned int (*fr_measure)(void); + struct clk *msr_clk; + unsigned int (*vs_measure)(int index); + void (*msr_ctrl_init)(struct platform_device *pdev, struct vout_mux_data_s *vdata); void (*update_viu_mux)(int index, unsigned int mux_sel); void (*clear_viu_mux)(int index, unsigned int mux_sel); }; @@ -35,56 +37,138 @@ struct vout_mux_data_s { static struct vout_mux_data_s *vout_mux_data; static int vout_vdo_meas_init; +/* ********************************************************** + * vout vsync measure + * ********************************************************** + */ +static void vout_meas_ctrl_init_dft(struct platform_device *pdev, struct vout_mux_data_s *vdata) +{ + struct clk *fclk_div5; + unsigned int clk_msr_val; + + if (!vdata) + return; + + fclk_div5 = clk_get(&pdev->dev, "fclk_div5"); + if (IS_ERR_OR_NULL(fclk_div5)) { + VOUTERR("%s: get fclk_div5 err!\n", __func__); + return; + } + vdata->msr_clk = clk_get(&pdev->dev, "vdin_meas_clk"); + if (IS_ERR_OR_NULL(vdata->msr_clk)) { + VOUTERR("%s: get vdin_meas_clk err!\n", __func__); + vdata->msr_clk = NULL; + return; + } + + clk_set_parent(vdata->msr_clk, fclk_div5); + clk_set_rate(vdata->msr_clk, VDIN_MEAS_CLK_FREQ); + clk_prepare_enable(vdata->msr_clk); + clk_msr_val = clk_get_rate(vdata->msr_clk); + VOUTPR("%s: vdin_meas_clk %dHZ\n", __func__, clk_msr_val); + + vout_vcbus_write(VPP_VDO_MEAS_CTRL, 0); + vout_vdo_meas_init = 1; +} + +static void vout_meas_ctrl_init_s5(struct platform_device *pdev, struct vout_mux_data_s *vdata) +{ + struct clk *fclk_div5; + unsigned int clk_msr_val; + + if (!vdata) + return; + + fclk_div5 = clk_get(&pdev->dev, "fclk_div5"); + if (IS_ERR_OR_NULL(fclk_div5)) { + VOUTERR("%s: get fclk_div5 err!\n", __func__); + return; + } + vdata->msr_clk = clk_get(&pdev->dev, "vdin_meas_clk"); + if (IS_ERR_OR_NULL(vdata->msr_clk)) { + VOUTERR("%s: get vdin_meas_clk err!\n", __func__); + vdata->msr_clk = NULL; + return; + } + + clk_set_parent(vdata->msr_clk, fclk_div5); + clk_set_rate(vdata->msr_clk, VDIN_MEAS_CLK_FREQ); + clk_prepare_enable(vdata->msr_clk); + clk_msr_val = clk_get_rate(vdata->msr_clk); + VOUTPR("%s: vdin_meas_clk %dHZ\n", __func__, clk_msr_val); + + vout_vcbus_setb(VPU_VENC_CTRL, 0, 8, 11); + vout_vdo_meas_init = 1; +} + static inline unsigned int vout_do_div(unsigned long long num, unsigned int den) { unsigned long long val = num; + if (den == 0) + return 0; + do_div(val, den); return (unsigned int)val; } -void vout_vdo_meas_ctrl_init(void) +static unsigned int vout_vs_measure_dft(int index) { - vout_vcbus_write(VPP_VDO_MEAS_CTRL, 0); - vout_vdo_meas_init = 1; -} + unsigned int val, fr = 0; + unsigned long long clk_msr = VDIN_MEAS_CLK_FREQ; -static unsigned int vout_frame_rate_measure_dft(void) -{ - int clk_mux = -1; - unsigned int val[2], fr = 0; - unsigned long long msr_clk; - - if (vout_mux_data) - clk_mux = vout_mux_data->vdin_meas_id; - - if (clk_mux == -1) + if (index > 1) return 0; if (vout_vdo_meas_init == 0) return 0; - //msr_clk = meson_clk_measure(clk_mux); - msr_clk = 50000000; - - val[0] = vout_vcbus_read(VPP_VDO_MEAS_VS_COUNT_HI); - val[1] = vout_vcbus_read(VPP_VDO_MEAS_VS_COUNT_LO); - msr_clk *= 1000; - if (val[0] & 0xffff) - return 0; - if (val[1]) - fr = vout_do_div(msr_clk, val[1]); + clk_msr *= 1000; + val = vout_vcbus_read(VPP_VDO_MEAS_VS_COUNT_LO); + fr = vout_do_div(clk_msr, val); return fr; } -unsigned int vout_frame_rate_measure(void) +static unsigned int vout_vs_measure_s5(int index) +{ + struct vinfo_s *vinfo = NULL; + unsigned int venc_index, val, fr; + unsigned long long clk_msr = VDIN_MEAS_CLK_FREQ; + + if (vout_vdo_meas_init == 0) + return 0; + if (index == 1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (index == 2) + vinfo = get_current_vinfo2(); +#endif +#ifdef CONFIG_AMLOGIC_VOUT3_SERVE + else if (index == 3) + vinfo = get_current_vinfo3(); +#endif + if (!vinfo) + return 0; + venc_index = (vinfo->viu_mux >> 4) & 0xf; + if (venc_index >= 1) + return 0; + + clk_msr *= 1000; + val = vout_vcbus_read(VPU_VENC_RO_MEAS0); + fr = vout_do_div(clk_msr, val); + + return fr; +} + +unsigned int vout_frame_rate_measure(int index) { unsigned int fr; - if (!vout_mux_data || !vout_mux_data->fr_measure) + if (!vout_mux_data || !vout_mux_data->vs_measure) return 0; - fr = vout_mux_data->fr_measure(); + + fr = vout_mux_data->vs_measure(index); return fr; } @@ -108,13 +192,13 @@ static void vout_viu_mux_update_default(int index, unsigned int mux_sel) } viu_sel = mux_sel & 0xf; - /* - *VOUTPR("%s: before: 0x%04x=0x%08x, 0x%04x=0x%08x\n", - * __func__, VPU_VIU_VENC_MUX_CTRL, - * vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL), - * VPU_VENCX_CLK_CTRL, - * vout_vcbus_read(VPU_VENCX_CLK_CTRL)); - */ + if (vout_debug_print) { + VOUTPR("%s: before: 0x%04x=0x%08x, 0x%04x=0x%08x\n", + __func__, VPU_VIU_VENC_MUX_CTRL, + vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL), + VPU_VENCX_CLK_CTRL, + vout_vcbus_read(VPU_VENCX_CLK_CTRL)); + } switch (viu_sel) { case VIU_MUX_ENCL: @@ -134,15 +218,15 @@ static void vout_viu_mux_update_default(int index, unsigned int mux_sel) vout_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, viu_sel, mux_bit, 2); if (clk_bit < 0xff) vout_vcbus_setb(VPU_VENCX_CLK_CTRL, clk_sel, clk_bit, 1); - /* - *VOUTPR("%s: %d, viu_sel=%d, mux_bit=%d, clk_sel=%d clk_bit=%d\n", - * __func__, index, viu_sel, mux_bit, clk_sel, clk_bit); - *VOUTPR("%s: after: 0x%04x=0x%08x, 0x%04x=0x%08x\n", - * __func__, VPU_VIU_VENC_MUX_CTRL, - * vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL), - * VPU_VENCX_CLK_CTRL, - * vout_vcbus_read(VPU_VENCX_CLK_CTRL)); - */ + if (vout_debug_print) { + VOUTPR("%s: %d, viu_sel=%d, mux_bit=%d, clk_sel=%d clk_bit=%d\n", + __func__, index, viu_sel, mux_bit, clk_sel, clk_bit); + VOUTPR("%s: after: 0x%04x=0x%08x, 0x%04x=0x%08x\n", + __func__, VPU_VIU_VENC_MUX_CTRL, + vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL), + VPU_VENCX_CLK_CTRL, + vout_vcbus_read(VPU_VENCX_CLK_CTRL)); + } } static void vout_viu_mux_update_t7(int index, unsigned int mux_sel) @@ -181,12 +265,13 @@ static void vout_viu_mux_update_t7(int index, unsigned int mux_sel) vout_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, venc_idx, viu_bit, 2); } - /*VOUTPR("%s: index=%d, mux_sel=0x%x, venc_idx=%d\n", - * __func__, index, mux_sel, venc_idx); - *VOUTPR("%s: 0x%04x=0x%08x\n", - * __func__, VPU_VIU_VENC_MUX_CTRL, - * vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL)); - */ + if (vout_debug_print) { + VOUTPR("%s: index=%d, mux_sel=0x%x, venc_idx=%d\n", + __func__, index, mux_sel, venc_idx); + VOUTPR("%s: 0x%04x=0x%08x\n", + __func__, VPU_VIU_VENC_MUX_CTRL, + vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL)); + } } static void vout_viu_mux_update_t3(int index, unsigned int mux_sel) @@ -222,12 +307,13 @@ static void vout_viu_mux_update_t3(int index, unsigned int mux_sel) vout_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, venc_idx, viu_bit, 2); } - /* VOUTPR("%s: index=%d, mux_sel=0x%x, venc_idx=%d\n", - * __func__, index, mux_sel, venc_idx); - * VOUTPR("%s: 0x%04x=0x%08x\n", - * __func__, VPU_VIU_VENC_MUX_CTRL, - * vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL)); - */ + if (vout_debug_print) { + VOUTPR("%s: index=%d, mux_sel=0x%x, venc_idx=%d\n", + __func__, index, mux_sel, venc_idx); + VOUTPR("%s: 0x%04x=0x%08x\n", + __func__, VPU_VIU_VENC_MUX_CTRL, + vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL)); + } } static void vout_viu_mux_clear_t7(int index, unsigned int mux_sel) @@ -236,8 +322,10 @@ static void vout_viu_mux_clear_t7(int index, unsigned int mux_sel) unsigned int reg_value, venc_dmy; reg_value = vout_vcbus_read(VPU_VIU_VENC_MUX_CTRL); - VOUTPR("%s: index=%d, mux_sel=0x%x\n", __func__, index, mux_sel); - VOUTPR("%s: viu_mux reg=0x%x\n", __func__, reg_value); + if (vout_debug_print) { + VOUTPR("%s: index=%d, mux_sel=0x%x\n", __func__, index, mux_sel); + VOUTPR("%s: viu_mux reg=0x%x\n", __func__, reg_value); + } viu_sel = mux_sel & 0xf; if (viu_sel == VIU_MUX_PROJECT) { @@ -270,29 +358,41 @@ void vout_viu_mux_clear(int index, unsigned int mux_sel) /* ********************************************************* */ static struct vout_mux_data_s vout_mux_match_data = { - .vdin_meas_id = 38, - .fr_measure = vout_frame_rate_measure_dft, + .msr_clk = NULL, + .vs_measure = vout_vs_measure_dft, + .msr_ctrl_init = vout_meas_ctrl_init_dft, .update_viu_mux = vout_viu_mux_update_default, .clear_viu_mux = NULL, }; static struct vout_mux_data_s vout_mux_match_data_t7 = { - .vdin_meas_id = 60, - .fr_measure = vout_frame_rate_measure_dft, + .msr_clk = NULL, + .vs_measure = vout_vs_measure_dft, + .msr_ctrl_init = vout_meas_ctrl_init_dft, .update_viu_mux = vout_viu_mux_update_t7, .clear_viu_mux = vout_viu_mux_clear_t7, }; static struct vout_mux_data_s vout_mux_match_data_t3 = { - .vdin_meas_id = 60, - .fr_measure = vout_frame_rate_measure_dft, + .msr_clk = NULL, + .vs_measure = vout_vs_measure_dft, + .msr_ctrl_init = vout_meas_ctrl_init_dft, .update_viu_mux = vout_viu_mux_update_t3, .clear_viu_mux = vout_viu_mux_clear_t7, }; static struct vout_mux_data_s vout_mux_match_data_t5w = { - .vdin_meas_id = 38, - .fr_measure = vout_frame_rate_measure_dft, + .msr_clk = NULL, + .vs_measure = vout_vs_measure_dft, + .msr_ctrl_init = vout_meas_ctrl_init_dft, + .update_viu_mux = vout_viu_mux_update_t3, + .clear_viu_mux = vout_viu_mux_clear_t7, +}; + +static struct vout_mux_data_s vout_mux_match_data_s5 = { + .msr_clk = NULL, + .vs_measure = vout_vs_measure_s5, + .msr_ctrl_init = vout_meas_ctrl_init_s5, .update_viu_mux = vout_viu_mux_update_t3, .clear_viu_mux = vout_viu_mux_clear_t7, }; @@ -318,6 +418,10 @@ static const struct of_device_id vout_mux_dt_match_table[] = { .compatible = "amlogic, vout_mux-t5m", .data = &vout_mux_match_data_t3, }, + { + .compatible = "amlogic, vout_mux-s5", + .data = &vout_mux_match_data_s5, + }, {} }; @@ -332,7 +436,8 @@ static int vout_mux_probe(struct platform_device *pdev) } vout_mux_data = (struct vout_mux_data_s *)match->data; - vout_vdo_meas_ctrl_init(); + if (vout_mux_data->msr_ctrl_init) + vout_mux_data->msr_ctrl_init(pdev, vout_mux_data); VOUTPR("%s OK\n", __func__); diff --git a/drivers/media/vout/vout_serve/vout_reg.h b/drivers/media/vout/vout_serve/vout_reg.h index 19557a1a7..ddca13424 100644 --- a/drivers/media/vout/vout_serve/vout_reg.h +++ b/drivers/media/vout/vout_serve/vout_reg.h @@ -237,6 +237,9 @@ #define VPP_VDO_MEAS_CTRL 0x1da8 #define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9 #define VPP_VDO_MEAS_VS_COUNT_LO 0x1daa +/* S5 */ +#define VPU_VENC_RO_MEAS0 0x1cfe +#define VPU_VENC_RO_MEAS1 0x1cff /* HIU */ #define HHI_VIID_CLK_DIV 0x4a diff --git a/drivers/media/vout/vout_serve/vout_serve.c b/drivers/media/vout/vout_serve/vout_serve.c index 1e71689dd..2820f0685 100644 --- a/drivers/media/vout/vout_serve/vout_serve.c +++ b/drivers/media/vout/vout_serve/vout_serve.c @@ -215,7 +215,7 @@ static irqreturn_t vout_vsync_irq_handler(int irq, void *data) case VMODE_DUMMY_ENCP: case VMODE_DUMMY_ENCI: case VMODE_DUMMY_ENCL: - fr = vout_frame_rate_measure(); + fr = vout_frame_rate_measure(1); vinfo->sync_duration_num = fr; vinfo->sync_duration_den = 1000; break; @@ -498,7 +498,7 @@ static ssize_t vout_frame_rate_show(struct class *class, unsigned int fr; int ret = 0; - fr = vout_frame_rate_measure(); + fr = vout_frame_rate_measure(1); ret = sprintf(buf, "%d.%03d\n", (fr / 1000), (fr % 1000)); return ret; @@ -547,7 +547,7 @@ static ssize_t vout_vinfo_show(struct class *class, if (!info) return sprintf(buf, "current vinfo is null\n"); - fr = vout_frame_rate_measure(); + fr = vout_frame_rate_measure(1); len = sprintf(buf, "current vinfo:\n" " name: %s\n" " mode: %d\n" diff --git a/include/linux/amlogic/media/vout/vout_notify.h b/include/linux/amlogic/media/vout/vout_notify.h index 7e8a87a54..0811273a0 100644 --- a/include/linux/amlogic/media/vout/vout_notify.h +++ b/include/linux/amlogic/media/vout/vout_notify.h @@ -301,5 +301,5 @@ int set_vout_mode_name(char *name); enum vmode_e validate_vmode(char *name, unsigned int frac); int set_current_vmode(enum vmode_e mode); void disable_vout_mode_set_sysfs(void); -unsigned int vout_frame_rate_measure(void); +unsigned int vout_frame_rate_measure(int index); #endif /* _VOUT_NOTIFY_H_ */