As your code is not time bound (in order for real-time frequency to work) you need to first define how much width represents one cycle (@ 1 Hz, or one second if you will).
Lets say the whole canvas width represents one cycle then we can do this:
var period = x / canvas.width; // period (one cycle)
To use that value change the formula slightly to:
return amplitude * Math.sin(freq * 2 * Math.PI * period);
If your frequency is 1 Hz one cycle will be drawn in the canvas area, if 2 Hz two cycles and so on.
The next thing you need to adjust is how you use the returned sine value. As of now you are simply accumulating the value. This will create a lag so the better approach is to treat the returned value as an absolute value since you're already using amplitude with it.
So change this line:
dotY += sineY(dotX);
to
dotY = canvas.height * 0.5 - 2.5 + sineY(dotX);
Now the dotY will draw the current sine value relative to the axis which means 0° will start at the axis' 0 position. You can now adjust amplitude etc.
This fiddle shows 20 cycles per canvas width as the frequency is set to 20 Hz.
(ps: I did not address phase here)
Hope this helps!